[hibernate-issues] [Hibernate-JIRA] Created: (HHH-4803) Injecting target into proxy in org.hibernate.envers.tools.Tools#getTargetFromProxy can cause duplicate entities in session
Gail Badner (JIRA)
noreply at atlassian.com
Fri Jan 15 02:24:29 EST 2010
Injecting target into proxy in org.hibernate.envers.tools.Tools#getTargetFromProxy can cause duplicate entities in session
--------------------------------------------------------------------------------------------------------------------------
Key: HHH-4803
URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-4803
Project: Hibernate Core
Issue Type: Bug
Components: envers
Affects Versions: 3.5.0-Beta-3
Reporter: Gail Badner
I believe that problems can arise if Tools.getTargetFromProxy(...) injects the target into the proxy. It is possible that the target entity will be duplicated in the session and cause an exception to be thrown.
Here is a (very contrived) scenario where this can happen:
X has a lazy many-to-one association with Y with cascade="all"
Both X and Y have a non-lazy many-to-one association with Z with cascade == "all"
s: original session
sTemp: temporary session
The entities, x, y, and z have already been persisted with the following associations:
x.y == y
x.z == null
y.z == z
In a new session/transaction:
X x = ( X ) s.get( X.class, xId );
Y yProxy = x.getY();
Z z = ( Z ) s.get( Z.class, zId );
z.setName( "new name" );
x.setZ( z );
s.update( x );
When changes to x are audited, Tools.getTargetFromProxy(...) is called to get the entity target for yProxy from a temporary session (sTemp) and inject that target back into yProxy.
Because of the non-lazy association between Y and Z, yProxy.z is also initialized in the temporary session. yProxy.z should refer to the same instance as z, but they are different instances because they were loaded into different sessions. In addition, the two instances have different state:
- z has a non-flushed update
- yProxy.z has the same state as loaded (w/o the update)
In other words:
z != yProxy.z && ! z.equals( yProxy.z )
Later, when an operation cascades to yProxy.z (e.g., during flush) and it's added to the session, an exception will be thrown because an updated version of the same entity is already present.
The safest way to avoid subtle problems like this is for Tools.getTargetFromProxy(...) to leave the proxy uninitialized (instead of injecting the target).
--
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.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
More information about the hibernate-issues
mailing list