Injecting target into proxy in org.hibernate.envers.tools.Tools#getTargetFromProxy can cause duplicate entities in session

Description

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).

Environment

None

Activity

Show:
Steve Ebersole
October 27, 2015, 7:14 PM

This bug report does not indicate that the reported issue affects version 5.x. Versions prior to 5.x are no longer maintained. It would be a great help to the Hibernate team and community for someone to verify that the reported issue still affects version 5.x. If so, please add the 5.x version that you verified with to the list of affected-versions and attach the (preferably SSCCE) test case you used to do the verification to the report; from there the issues will be looked at during our triage meetings.

For details, see http://in.relation.to/2015/10/27/great-jira-cleanup-2015/

Steve Ebersole
October 28, 2015, 3:25 AM

As part of verifying that this issue affects 5.0, please just set the "Affects version". Leave the "verify-affects-5.0" label and leave the issue in "Awaiting Response" status; these are critical for us to be able to track these verifications and triage them. Thanks.

Chris Cranford
January 11, 2017, 4:50 PM

, I have been trying to reproduce this and haven't been successful.

I added a commit in my fork for a test case https://github.com/Naros/hibernate-orm/commits/HHH-4803.

When I test this, EntityZ is never proxied so the #getTargetFromProxy isn't called when creating the CollectionChangeWorkUnit. Perhaps you could skim my test case and let me know what I might have overlooked based on your provided example in this JIRA.

Assignee

Unassigned

Reporter

Gail Badner

Fix versions

None

Labels

backPortable

None

Suitable for new contributors

None

Requires Release Note

Affirmative

Pull Request

None

backportDecision

None

Components

Affects versions

Priority

Major
Configure