Problem in caching proper natural-id-values when obtaining result by naturalIdQuery
-----------------------------------------------------------------------------------
Key: HHH-7287
URL:
https://hibernate.onjira.com/browse/HHH-7287
Project: Hibernate ORM
Issue Type: Bug
Components: core
Affects Versions: 4.1.2
Environment: Database access with isolation level < SNAPSHOT
Reporter: Guenther Demetz
Problem was originally exposed by Madhumita Sadhukhan in a email to
hibernate-dev(a)lists.jboss.org at Fri 4/27/2012 .
The bug (email point 6) get isolated by following matrix-test-case:
{code:title=org.hibernate.test.naturalid.mutable.MutableNaturalIdTest.java|borderStyle=solid}
@Test
public void testModificationInOtherSession() {
Session s = openSession();
Transaction t = s.beginTransaction();
User u = new User( "gavin", "hb", "secret" );
s.persist( u );
t.commit();
s.close();
s = openSession();
// Use transactionless session
assertNotNull( s.byNaturalId( User.class ).using( "name", "gavin"
).using( "org", "hb" ).load());
// CHANGE natural-id values in another session
Session other = openSession();
other.beginTransaction();
u = (User) other.byId( User.class ).getReference( u.getId() );
u.setOrg( "zz" );
other.getTransaction().commit();
other.close();
// CHANGE APPLIED
u = (User) s.byId( User.class ).getReference( u.getId() );
assertEquals(u, s.byNaturalId( User.class ).using( "name", "gavin"
).using( "org", "hb" ).load()); // found with cached old-values, OK
User u2 = (User) s.byNaturalId( User.class ).using( "name", "gavin"
).using( "org", "zz" ).load(); // the internal query will
'see' the new values, because isolation level < SERIALIZABLE
assertEquals(u, u2); // is it right here having u2 != null ? Yes, if we continue to see
NaturalIdLoadAccess as a plain query. Maybe something to discuss
assertEquals("hb", u2.getOrg()); // entity itself must still contain the old
value
assertNotNull( s.byNaturalId( User.class ).using( "name", "gavin"
).using( "org", "hb" ).load()); // this fails, that's the bug
s.close();
s = openSession();
s.beginTransaction();
s.delete( u );
s.getTransaction().commit();
s.close();
}
{code}
CAUSE:
The problem raises, when natural-id get resolved by query.
Here Hiberante uses the search-natural-id values for updating the cache, probably not
being aware that in such situation they could differ from the natural-id-values in the
current entity state. The cache-update then detects the old-values as obsolete and removes
them, this explains why the second lookup with old values suddently returns null.
SOLUTION PROPOSAL:
After natural-id get resolved from query, first load the entity by identifier, and then
cache the natural-id-values taking them from the entity state.
--
This message is automatically generated by JIRA.
For more information on JIRA, see:
http://www.atlassian.com/software/jira