4.4.2. Extended entity manager and automatic versioning
A single persistence context is used for the whole application transaction. The entity manager checks instance versions at flush time, throwing an exception if concurrent modification is detected. It's up to the developer to catch and handle this exception (common options are the opportunity for the user to merge his changes or to restart the business process with non-stale data).
EXTENDEDpersistence context, all operations made outside an active transaction are queued. The
EXTENDEDpersistence context is flushed when executed in an active transaction (at worse at commit time).
Entity Manageris disconnected from any underlying JDBC connection when waiting for user interaction. In an application-managed extended entity manager, this occurs automatically at transaction completion. In a stateful session bean holding a container-managed extended entity manager (i.e. a SFSB annotated with
@PersistenceContext(EXTENDED)), this occurs transparently as well. This approach is the most efficient in terms of database access. The application need not concern itself with version checking or with merging detached instances, nor does it have to reload instances in every database transaction. For those who might be concerned by the number of connections opened and closed, remember that the connection provider should be a connection pool, so there is no performance impact. The following examples show the idiom in a non-managed environment:
// foo is an instance loaded earlier by the extended entity manager em.getTransaction().begin(); // new connection to data store is obtained and tx started foo.setProperty("bar"); em.getTransaction().commit(); // End tx, flush and check version, disconnect
fooobject still knows which
persistence contextit was loaded in. With
getTransaction.begin();the entity manager obtains a new connection and resumes the persistence context. The method
getTransaction().commit()will not only flush and check versions, but also disconnects the entity manager from the JDBC connection and return the connection to the pool.
This pattern is problematic if the persistence context is too big to be stored during user think time, and if you don't know where to store it. E.g. the
HttpSessionshould be kept as small as possible. As the persistence context is also the (mandatory) first-level cache and contains all loaded objects, we can probably use this strategy only for a few request/response cycles. This is indeed recommended, as the persistence context will soon also have stale data.
It is up to you where you store the extended entity manager during requests, inside an EJB3 container you simply use a stateful session bean as described above. Don't transfer it to the web layer (or even serialize it to a separate tier) to store it in the
HttpSession. In a non-managed, two-tiered environment the
HttpSessionmight indeed be the right place to store it.