diff --git a/hibernate-core/src/main/java/org/hibernate/cache/spi/NaturalIdCacheKey.java b/hibernate-core/src/main/java/org/hibernate/cache/spi/NaturalIdCacheKey.java index bd0a7624ea..b852b8af4e 100644 --- a/hibernate-core/src/main/java/org/hibernate/cache/spi/NaturalIdCacheKey.java +++ b/hibernate-core/src/main/java/org/hibernate/cache/spi/NaturalIdCacheKey.java @@ -33,6 +33,7 @@ import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.util.ValueHolder; import org.hibernate.internal.util.compare.EqualsHelper; import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.type.EntityType; import org.hibernate.type.Type; /** @@ -81,7 +82,15 @@ public class NaturalIdCacheKey implements Serializable { result = prime * result + (value != null ? type.getHashCode( value, factory ) : 0); - this.naturalIdValues[i] = type.disassemble( value, session, null ); + // The natural id may not be fully resolved in some situations. See HHH-7513 for one of them + // (re-attaching a mutable natural id uses a database snapshot and hydration does not resolve associations). + // TODO: The snapshot should probably be revisited at some point. Consider semi-resolving, hydrating, etc. + if (type instanceof EntityType && type.getSemiResolvedType( factory ).getReturnedClass().isInstance( value )) { + this.naturalIdValues[i] = (Serializable) value; + } + else { + this.naturalIdValues[i] = type.disassemble( value, session, null ); + } } this.hashCode = result; diff --git a/hibernate-core/src/test/java/org/hibernate/test/naturalid/mutable/cached/CachedMutableNaturalIdTest.java b/hibernate-core/src/test/java/org/hibernate/test/naturalid/mutable/cached/CachedMutableNaturalIdTest.java index ac4043f842..faf4237dba 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/naturalid/mutable/cached/CachedMutableNaturalIdTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/naturalid/mutable/cached/CachedMutableNaturalIdTest.java @@ -23,21 +23,19 @@ */ package org.hibernate.test.naturalid.mutable.cached; -import java.io.Serializable; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; -import org.junit.Test; +import java.io.Serializable; import org.hibernate.LockOptions; import org.hibernate.Session; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; -import org.hibernate.testing.FailureExpected; import org.hibernate.testing.TestForIssue; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; /** * Tests of mutable natural ids stored in second level cache @@ -185,7 +183,6 @@ public abstract class CachedMutableNaturalIdTest extends BaseCoreFunctionalTestC } @Test - @FailureExpected(jiraKey = "HHH-7513") public void testReattachementUnmodifiedInstance() { Session session = openSession(); session.beginTransaction(); @@ -197,16 +194,19 @@ public abstract class CachedMutableNaturalIdTest extends BaseCoreFunctionalTestC b.assA = a; a.assB.add( b ); session.getTransaction().commit(); - session.close(); + session.clear(); - session = openSession(); session.beginTransaction(); session.buildLockRequest(LockOptions.NONE).lock(b); // HHH-7513 failure during reattachment session.delete(b.assA); session.delete(b); session.getTransaction().commit(); - session.close(); + session.clear(); + + // true if the re-attachment worked + assertEquals( session.createQuery( "FROM A" ).list().size(), 0 ); + assertEquals( session.createQuery( "FROM B" ).list().size(), 0 ); } }