diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/OneToOneSecondPass.java b/hibernate-core/src/main/java/org/hibernate/cfg/OneToOneSecondPass.java index a428cd3465..a922034d74 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/OneToOneSecondPass.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/OneToOneSecondPass.java @@ -32,6 +32,7 @@ import org.hibernate.annotations.common.reflection.XClass; import org.hibernate.cfg.annotations.PropertyBinder; import org.hibernate.internal.util.StringHelper; import org.hibernate.mapping.Column; +import org.hibernate.mapping.Component; import org.hibernate.mapping.DependantValue; import org.hibernate.mapping.Join; import org.hibernate.mapping.ManyToOne; @@ -212,7 +213,23 @@ public class OneToOneSecondPass implements SecondPass { propertyHolder.addProperty( prop, inferredData.getDeclaringClass() ); } - value.setReferencedPropertyName( mappedBy ); + // HHH-6813 + // If otherSide's id is derived, do not set EntityType#uniqueKeyPropertyName. + // EntityType#isReferenceToPrimaryKey() assumes that, if it's set, + // a PK is not referenced. Example: + // + // Foo: @Id long id, @OneToOne(mappedBy="foo") Bar bar + // Bar: @Id @OneToOne Foo foo + boolean referencesDerivedId = false; + try { + referencesDerivedId = otherSide.getIdentifier() instanceof Component + && ( (Component) otherSide.getIdentifier() ).getProperty( mappedBy ) != null; + } + catch ( MappingException e ) { + // ignore + } + String referencedPropertyName = referencesDerivedId ? null : mappedBy; + value.setReferencedPropertyName( referencedPropertyName ); String propertyRef = value.getReferencedPropertyName(); if ( propertyRef != null ) { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/bidirectional/OneToOneWithDerivedIdentityTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/bidirectional/OneToOneWithDerivedIdentityTest.java index 6183728f06..d530da8612 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/bidirectional/OneToOneWithDerivedIdentityTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/bidirectional/OneToOneWithDerivedIdentityTest.java @@ -23,14 +23,14 @@ */ package org.hibernate.test.annotations.derivedidentities.bidirectional; -import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import org.hibernate.Session; import org.hibernate.testing.FailureExpected; +import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; +import org.junit.Test; public class OneToOneWithDerivedIdentityTest extends BaseCoreFunctionalTestCase { @Test @@ -57,6 +57,29 @@ public class OneToOneWithDerivedIdentityTest extends BaseCoreFunctionalTestCase s.getTransaction().rollback(); s.close(); } + + @Test + @TestForIssue(jiraKey = "HHH-6813") + public void testSelectWithDerivedId() { + Session s = openSession(); + s.beginTransaction(); + Bar bar = new Bar(); + bar.setDetails( "Some details" ); + Foo foo = new Foo(); + foo.setBar( bar ); + bar.setFoo( foo ); + s.persist( foo ); + s.flush(); + assertNotNull( foo.getId() ); + assertEquals( foo.getId(), bar.getFoo().getId() ); + + s.clear(); + Foo newFoo = (Foo) s.createQuery( "SELECT f FROM Foo f" ).uniqueResult(); + assertNotNull( newFoo ); + assertEquals( "Some details", newFoo.getBar().getDetails() ); + s.getTransaction().rollback(); + s.close(); + } @Override protected Class[] getAnnotatedClasses() {