Managed Versus Unmanaged Entities
Before we can go any deeper into the entity manager service, we need to delve more deeply into the life cycle of entity object instances. An entity bean instance is either managed (a.k.a. attached) by an entity manager or unmanaged (a.k.a. detached). When an entity is attached to an EntityManager, the manager tracks state changes to the entity and synchronizes those changes to the database whenever the entity manager decides to flush its state. When an entity is detached, it is unmanaged. Any state changes to an entity that is detached are not tracked by the entity manager.
Persistence Context
A persistence context
is a set of managed entity object instances. Persistence contexts are managed by an entity manager. The entity manager tracks all entity objects within a persistence context for changes and updates made, and flushes these changes to the database using the flush mode rules discussed later in this chapter. Once a persistence context is closed, all managed entity object instances become detached and are no longer managed. Once an object is detached from a persistence context, it can no longer be managed by an entity manager, and any state changes to this object instance will not be synchronized with the database.
 |
When a persistence context is closed, all managed entity objects become detached and are unmanaged.
|
|
There are two types of persistence contexts: transaction-scoped
and extended persistence contexts.
Transaction-scoped persistence context
Persistence contexts may live as long as a transaction and be closed when a transaction completes. This is called a transaction-scoped persistence context
. When the transaction completes, the transaction-scoped persistence context will be destroyed and all managed entity object instances will become detached. Only application server managed persistence contexts can be transaction-scoped. In other words, only EntityManager instances injected with the @PersistenceContext annotation or its XML equivalent may be transaction-scoped.
@PersistenceContext
(unitName="titan")
EntityManager entityManager;
@TransactionAttribute(REQUIRED)
public Customer someMethod( ) {
Customer cust = entityManager.find(Customer.class, 1);
cust.setName("new name");
return cust;
}
When someMethod( ) is executed, the EJB container invokes it within the context of a JTA transaction. A customer reference is pulled from the EntityManager, and the setName( ) method is used to change the name of the customer. The Customer instance that the EntityManager returns will remain managed for the duration of the JTA transaction. This means that the change made by calling the setName( ) method will be synchronized with the database when the JTA transaction completes and commits. The Customer instance is returned by someMethod( ). After the JTA transaction completes, the transaction-scoped persistence context is destroyed, and this Customer instance is no longer managed. This means that if setName( ) is called after it becomes detached, no changes will be made to any database.
Extended persistence context
Persistence contexts may also be configured to live longer than a transaction. This is called an extended
persistence context
. Entity object instances that are attached to an extended context remain managed even after a transaction is complete. This feature is extremely useful in situations where you want to have a conversation with your database but not keep a long-running transaction, as transactions hold valuable resources like JDBC connections and database locks. Here's some small pseudocode to illustrate this concept:
Customer cust = null;
transaction.begin( ); // start transaction 1
cust = extendedEntityManager.find(Customer.class, 1);
transaction.commit( ); // transaction 1 ends
transaction.begin( ); // start transaction 2
cust.setName("Bill");
extendedEntityManager.flush( );
transaction.commit( ); // cust instance remains managed and changes are flushed
In this example, a local variable, cust, is initialized by calling the find( ) method in transaction 1. Unlike a transaction-scoped persistence context, the Customer instance pointed to by this local variable remains managed. This is because persistence context stays alive past the completion of transaction 1. In transaction 2, the customer is updated and the changes are flushed to the database.
Extended persistence contexts may be created and managed by application code. We'll see examples of this later in this chapter. They can also be created and managed by stateful session beans. You can see examples of the integration between stateful session beans and extended persistence contexts in chapter-11.
Detached entities
Entity instances become unmanaged and detached when a transaction scope or extended persistence context ends. An interesting side effect is that detached entities
can be serialized and sent across the network to a remote client. The client can make changes remotely to these serialized object instances and send them back to the server to be merged back and synchronized with the database.
This behavior is very different from the EJB 2.1 entity model,
where entities are always managed by the container. In EJB 2.1, applications using entity beans always had a proxy to the entity bean; in EJB 3.0, you work with concrete instances of plain Java classes. For EJB 2.1 developers, this behavior will seem strange at first, since you are used to the container managing every aspect of the entity. You'll find that after you get used to the new EJB 3.0 model, your application code actually shrinks and is easier to manage.
EJB 2.1 code often used the Value Object Pattern
(often called Data Transfer Objects). The idea of this pattern was that the entity bean exposed a method that copied its entire state into an object that could be serialized to remote clients (like a Swing application) that needed access to the entity's state:
// EJB 2.1 Entity bean class
public class CustomerBean implements javax.ejb.EntityBean {
CustomerValueObject getCustomerVO( ) {
return new CustomerValueObject(getFirstName( ), getLastName( ),
getStreet( ), getCity( ), getState, getZip( ));
}
}
It is very expensive to make a remote method call to an entity bean from a client. If the client had to call getFirstName( ), getLastName( ), etc., to get information about a customer it was displaying, performance would suffer. This is where the Value Object Pattern came in. EJB 3.0 eliminates the need for this pattern because persistent objects become value objects automatically when they are detached from a persistent context.
 |