First apologies for this long email but this subject and its solution are
close to my heart and I would like for once to put this to bed.

David thanks for setting the stage for this post. Reading your post made me
feel so much better about what we are doing. I am now more convinced than
ever about what we have built; its so right for so many and at the right
time and not 3 years down the line as you indicated.



<david>

The problem:

There are just flaws in the EJB 1.1 spec (2.0 will surely fix a few of them)
that cause <david>

1. more reads than necessary,
2. make it hard for objects to span multiple tables
3. make updates to objects more frequent than necessary
4. confuse programmers into designing entity beans to be mirrors of their
SQL tables instead of objects
5. complicate the clear needs of main independent business objects to have
relationships to many dependent objects
which also need to persist, etc.
6. by doing your own JDBC, you can optimize the way objects are loaded,
unloaded, saved, updated, etc.
7. often when doing an update on an object, you really only are changing a
state attribute or something minor.  There's no need to update the entire
object's attributes, only that one attribute (SQL: UPDATE UserTbl SET
visit_count=visit_count+1).
8. optimistic locking-style updates to the persistent store.
9. I think EJBs are wonderful, but no 3 year old technology can be robust
yet, especially when it needs to serve so many existing TP systems.

<david>



Lucky for you, David, there is one vendor who is provding all this support
in their container without you having to go out and buy any WeightGain
powder products to beef things up. We all know that really this just puts
fat on instead of lean muscle; fat cannot turn to muscle. Its hard to beat
your body type so next time choose a different body to contain your life
force.

Please allow me to put on my vendor hat : Inprise Application Server 4.1 .

<vendor>

The solution:

1. A simplistic scheme is that the state of an entity be only cached for the
duration of a transaction. Beans stay in the ready state for the duration of
the current transaction, or until they are removed. The only optimizations
can be in the CMP engine: (Tuned Writes) avoiding doing
        updates if the data did not change
        only updating the fields that were modified

However we go beyond the basics and you can specify any of the three modes
outlined in the EJB specification.
* Option A: exclusive database access, retains state across transactions
* Option B: avoid passivation/activation across transactions
* Option C: passivate/activate across transactions (the behaviour above)

Note that Option A, in conjunction with field-level modification-detection
in the CMP engine, will allow repeated readonly transaction to run
completely in the container, e.g., without going to the database. This
should be very fast. Note that this option makes sense only when the entity
"owns" the data in the database. You will have problems if the database is
modified externally (eg by a data base administrator, another app) while the
EJB server is running.

2. The Inprise CMP engine facilitates a number of different object
relational mapping strategies. This section provides a conceptual overview
of these mapping strategies and shows how to implement them within the
Inprise EJB Container environment.

The most basic object relationship maps one entity bean to one (database)
table. An instance of an entity bean represents one row in a table and each
field in the bean represents a column in the table. A primary key that
matches the primary key identifier of the table row identifies the entity
bean instance. The attributes of the entity's primary key may be primitives,
serializable objects, or remote references. While all one-to-one
relationships are similar in concept, different attribute types require
different implementation approaches.

The Inprise CMP engine also handles more complex object relationships, such
as one-to-many and many-to-many relationships. The primary and foreign key
values are not limited to single column values. They can be composite keys;
that is, consisting of more than one column value. The engine also supports
the use of composite keys in the finder methods.

The object relational mapping can accommodate one entity bean spanning
multiple tables, even across multiple databases. Finder methods can span
multiple tables. In addition, you can use array parameters in the finder
methods, and the engine expands and uses the array in the where clause.

3. Our CMP engine can detect read-only access and avoid making SQL update
calls to the database with out the need for those 'DIRTY' flags. In the
event that a subset of the fields have changed we perform tuned writes. This
comes free to you without you having to generate all the db logic to
implement this feature.

While other EJB Container products use code generation to support CMP, the
Inprise Container does not use code generation because it has serious
limitations. For example, code generation makes it difficult to support a
"tuned update" feature, because of the great number of different update
statements to container-managed fields that are required.

4. Our CMP Engine allows your beans to reference other beans without you
having to have a cmp field with the id and another to hold the reference you
lookup through the home of the bean. This means your beans looks more OO
than DB. When using references among entity beans, you simply (and
naturally) have a field in the entity that is of the type of Remote
interface of the referred to entity. Then in the deployment descriptor you
need to map the field-name to the target entity by using an ejb-link. That's
it! The information provided in the XML DD is enough for the CMP engine to
locate the associated entity.

The container optimizes this cross-entity reference to be pretty much as
fast as just storing the value of the foreign key. Two important differences
are:

* You don't have to call Home.findByPrimaryKey(PK pk) to get the object
corresponding to the id.
* The state of the entity is only loaded when you actually use it.

5. The Inprise CMP engine uses a different approach to handle one-to-one
relationships where the fields are serializable objects and not primitives.
Serializable objects encompass data stored as a series of undifferentiated
bytes; in a database, a serializable object would be stored as a BLOB.

For example, you might have a Student entity bean with two fields: a String
field containing the student's name and an Address field containing the
student's home address--street, city, state, and so forth. The Address field
could be stored in the corresponding database table as a BLOB column.
However, because a BLOB is a series of undifferentiated bytes, database
users cannot easily access data within the BLOB, such as retrieving all
students who come from a certain state or who live in a particular city. It
is preferable to use separate columns for each address attribute.

The Inprise CMP engine lets you use a JavaBeanTM object to represent a
composite field such as Address. A JavaBean lets you decompose the data into
its separate fields. For example, with a field such as an Address object,
your Student table would have the following columns: name, street1, street2,
city, state, and zip. The corresponding Student entity bean would have a
field name and an Address object, but the Address object would be a JavaBean
object. The Address JavaBean object has five private fields: street1,
street2, city, state, and zip, with public getter and setter methods for
each field. Figure 7.7 illustrates this.

6. In tests we have shown that our CMP Engine can match and in some cases
out perform any JDBC SQL stuff you can write. Remember we can cache
prepared statements across transactions. We have tuned write and read-only
detection. We allow your to write your finder query in SQL without having to
use some other osbcure and less powerful query notation. This means your
selects can span tables and call all sql operands. You can also flag your
finder method calls to load the state and not just the pk which means less
SQL calls i..e less read see (1) above. Also note that your finders can look
more OO than just simple DB calls. Some information on our finders:

Parameter substitution
======================
Parameter substitution is an important part of the where clause. The Inprise
EJB Container does parameter substitution wherever it finds the standard SQL
substitution prefix colon (:). Each parameter for substitution corresponds
to a name of a parameter in the finder specification found in the XML
descriptor. For example, in the XML deployment descriptor, you might define
the following finder method which takes a parameter balance (note that
balance is preceded by a colon):

<finder>
<method-signature>findAccountsLargerThan(float balance)</method-signature>

<where-clause>balance > :balance</where-clause>
</finder>

The Container composes a SQL select statement whose where clause is: balance
> ?

Note that the :balance parameter in the deployment descriptor becomes a
question mark (?) in the equivalent SQL statement. When invoked, the
Container substitutes the value of the parameter :balance for the ? in the
where clause.

Compound parameters
===================

The Container also supports compound parameters; that is, the name of a
table followed by a column within the table. For this, it uses the standard
dot (.) syntax, where the table name is separated from the column name by a
dot. These parameters are also preceded by a colon.

For example, the following finder method has the compound parameters
:address.city and :address.state:

<finder>
<method-signature>findByCity(Address address)</method-signature>
<where-clause>city = :address.city AND state = :address.state</where-clause>
</finder>

The where clause uses the city and state fields of the address compound
object to select particular records. The underlying Address object could
have Java Beans-style getter methods that correspond to the attributes city
and state. Or, alternatively, it could have public fields that correspond to
the attributes.

Entity beans as parameters

An entity bean can also serve as a parameter in a finder method. You can use
an entity bean as a compound type; if so, you must tell the CMP engine which
field to use from the entity bean's passed reference to the SQL query. If
you do not use the entity bean as a compound type, then the Container
substitutes the bean's primary key in the where clause.

For example, suppose you have a set of OrderItems entity beans associated
with an Order entity object. You might have the following finder method:
java.util.Collection OrderItemHome.findByOrder(Order order);

This method returns all OrderItems associated with a particular Order. The
deployment descriptor entry for its where clause would be:

<finder>
<method-signature>findByOrder(Order order)</method-signature>
<where-clause>order_id = :order[ejb/orders]</where-clause>
</finder>

To produce this where clause, the Container substitutes the primary key of
the Order object for the string :order[ejb/orders]. The string between the
brackets (in this example, ejb/orders) must be the <ejb-ref> corresponding
to the home of the parameter type. In this example, ejb/orders corresponds
to an <ejb-ref> pointing to OrderHome.

When you use an EJBObject as a compound type (using the dot notation), you
are actually accessing the underlying get method for the field in the
<finder> definition. For example, the following in the <finder> definition:

order_id = :order.orderId

calls the getOrderId() method on the order EJBObject and uses the result of
the call in the selection criterion.

7. Tuned writes come free.

8. The section "Concurrent access from multiple transactions" of the EJB
specification discusses two types of entity access. We implement the model
for multiplexed access. That is, multiple clients can access the entity
simultaneously, without locking at the container level. Note that locking
may occur at the database, but will not occur in the container.
Transactions are used to control access to entity beans. If two different
transactions (e.g., clients) access the same entity, they will in fact see
different instances, each with a separate copy of the state. If the state is
modified in both transactions, then only one of the transactions will be
able to commit, and the other will abort. The concurrency control is done by
the database (more on this in other FAQs). All locking is provided by the
database, via isolation levels specified to the JDBC driver.

Note that the Container supports parallel transactional access to the same
entity. Other "popular" EJB containers serialize access to entities, by
locking. This will obviously have a severe impact on performance.

9. David, wake up the web has you.....

</vendor>

William Louth
Inprise Europe
[EMAIL PROTECTED]

===========================================================================
To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
of the message "signoff EJB-INTEREST".  For general help, send email to
[EMAIL PROTECTED] and include in the body of the message "help".

Reply via email to