Add ability to lock / reattach an entity with a dirty collection
----------------------------------------------------------------
Key: HHH-5514
URL:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-5514
Project: Hibernate Core
Issue Type: New Feature
Components: core
Environment: 3.3.2.GA, Oracle 10g
Reporter: Steve McIntyre
We are using Hibernate 3.3.2.GA, with optimistic locking via @Version and the session per
request pattern (and thus detached entity object graphs).
We have a very complex object graph consisting of carts, orders, line items, sub line
items, payments, delivery, sub line item deliveries, etc. In most situations, our cart
executes against a single order. However, there are cases where multiple orders can be
involved. Our orders can be fairly large in terms of the number of line items, sub items,
etc. As a result, as users navigate the application we only load the orders they request.
The issue gets more complex if two orders (e.g. order #1 and #2) are involved in multiple
carts. Why? Some entities in the object graph (e.g. carts, payments, deliveries, etc) can
span orders and transactions. Consider a multiple-step/session cart where we load order
#1, associate it with a new cart and detach the object graph. The user subsequently
requests elements from order #2 be loaded into the new cart. So, we load order #2,
associate it with the same/new cart and detach the object graph.
Now, if in a previous cart/transaction, orders #1 and #2 shared a (eg) delivery, when we
load #2 and its associated delivery, in order to avoid two instances of this same delivery
in our detached object graph, we need to re-attach the previously loaded delivery to the
new session, prior to loading order #2.
Since we are not ready to persist changes to the database yet, and because this delivery
may be dirty, we choose to use Hibernate's "lock" API (as opposed to
refresh, load, merge, update, etc) to re-attach the delivery in our graph to the current
session.
All this works great except that if our delivery entity has a pesisted collection that has
been modified, a "reassociated object has dirty collection" Hibernate exception
is thrown.
We could work around this situation by adding a new collection to our delivery entity that
maintained changes to the pesisted collection, then just prior to calling
"merge" we could move the changes to the persistence collection. However, as I
mentioned we have a complex object graph... that involves 10 entities with a total of 23
persisted collections we'd have to manage this way for this one aspect of our system.
As an experiment, I commented out one line in the org.hibernate.event.def.OnLockVisitor
class, processCollection method (below) to no longer throw the exception.
{noformat}
if ( persistentCollection.isDirty() ) {
// Don't throw exception hack
// throw new HibernateException( "reassociated object has dirty collection"
);
}
reattachCollection( persistentCollection, type );
{noformat}
and returned early from org.hibernate.event.def.DefaultLockEventListener class, onLock
method (below)
{noformat}
if ( !ForeignKeys.isNotTransient( event.getEntityName(), entity, Boolean.FALSE, source ) )
{
return; // Return early hack
// throw new TransientObjectException(
// "cannot lock an unsaved transient instance: " +
// persister.getEntityName()
// );
}
{noformat}
With these two changes, I was able to lock / re-attach all the necessary entities in our
detached object graph, and subsequently was able to merge the entire graph successfully.
My questions to the Hibernate team are:
1) Is there already existing functionality that could achieve the same results (e.g.
re-attach detached entities that contain dirty persistence collections to a new session
)?
2) Would they consider adding another org.hibernate.LockMode type (e.g. DIRTY) that would
support the behavior I've described above? If so on this latter option, I would be
happy to work on the code fix to support the DIRTY or maybe DIRTY_COLLECTION lock mode.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://opensource.atlassian.com/projects/hibernate/secure/Administrators....
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira