From 2bfe30009c15ea59c587d11714d4be78b14f9ad9 Mon Sep 17 00:00:00 2001 From: Vlad Mihalcea Date: Tue, 23 Jan 2018 10:19:52 +0200 Subject: [PATCH] HHH-9460 - Removing non-optional bidirectional @OneToOne association with cascade --- .../org/hibernate/cfg/OneToOneSecondPass.java | 20 +-- .../e4/b/MedicalHistory.java | 2 +- .../OneToOneMapsIdJoinColumnTest.java | 117 ++++++++++++++++++ .../BidirectionalOptionalOneToOneTest.java | 1 - 4 files changed, 131 insertions(+), 9 deletions(-) create mode 100644 hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OneToOneMapsIdJoinColumnTest.java 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 1859f5586d..30d8a1b17e 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/OneToOneSecondPass.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/OneToOneSecondPass.java @@ -8,7 +8,6 @@ package org.hibernate.cfg; import java.util.Iterator; import java.util.Map; - import javax.persistence.ConstraintMode; import org.hibernate.AnnotationException; @@ -92,12 +91,19 @@ public class OneToOneSecondPass implements SecondPass { value.setCascadeDeleteEnabled( cascadeOnDelete ); //value.setLazy( fetchMode != FetchMode.JOIN ); - if ( !optional ) value.setConstrained( true ); - value.setForeignKeyType( - value.isConstrained() - ? ForeignKeyDirection.FROM_PARENT - : ForeignKeyDirection.TO_PARENT - ); + if ( !optional ) { + value.setConstrained( true ); + } + if ( value.isReferenceToPrimaryKey() ) { + value.setForeignKeyType( ForeignKeyDirection.TO_PARENT ); + } + else { + value.setForeignKeyType( + value.isConstrained() + ? ForeignKeyDirection.FROM_PARENT + : ForeignKeyDirection.TO_PARENT + ); + } PropertyBinder binder = new PropertyBinder(); binder.setName( propertyName ); binder.setValue( value ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/b/MedicalHistory.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/b/MedicalHistory.java index 242086784a..face0b9e25 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/b/MedicalHistory.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/b/MedicalHistory.java @@ -25,7 +25,7 @@ public class MedicalHistory { @MapsId @JoinColumn(name = "FK") - @OneToOne(cascade= CascadeType.ALL) + @OneToOne(cascade= CascadeType.PERSIST) Person patient; @Temporal(TemporalType.DATE) diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OneToOneMapsIdJoinColumnTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OneToOneMapsIdJoinColumnTest.java new file mode 100644 index 0000000000..31c22b5b88 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetoone/OneToOneMapsIdJoinColumnTest.java @@ -0,0 +1,117 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.test.annotations.onetoone; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.MapsId; +import javax.persistence.OneToOne; + +import org.hibernate.annotations.NaturalId; +import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; + +import org.junit.Test; + +import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; + +/** + * @author Vlad Mihalcea + */ +public class OneToOneMapsIdJoinColumnTest extends BaseEntityManagerFunctionalTestCase { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + Person.class, + PersonDetails.class + }; + } + + @Test + public void testLifecycle() { + Person _person = doInJPA( this::entityManagerFactory, entityManager -> { + Person person = new Person( "ABC-123" ); + + PersonDetails details = new PersonDetails(); + details.setNickName( "John Doe" ); + + person.setDetails( details ); + entityManager.persist( person ); + + return person; + } ); + + doInJPA( this::entityManagerFactory, entityManager -> { + Person person = entityManager.find( Person.class, _person.getId() ); + + PersonDetails details = entityManager.find( PersonDetails.class, _person.getId() ); + } ); + } + + @Entity(name = "Person") + public static class Person { + + @Id + private String id; + + @OneToOne(mappedBy = "person", cascade = CascadeType.PERSIST, optional = false) + private PersonDetails details; + + public Person() {} + + public Person(String id) { + this.id = id; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public void setDetails(PersonDetails details) { + this.details = details; + details.setPerson( this ); + } + } + + @Entity(name = "PersonDetails") + public static class PersonDetails { + + @Id + private String id; + + private String nickName; + + @OneToOne + @MapsId + @JoinColumn(name = "person_id") + private Person person; + + public String getNickName() { + return nickName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } + + public Person getPerson() { + return person; + } + + public void setPerson(Person person) { + this.person = person; + } + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/onetoone/optional/BidirectionalOptionalOneToOneTest.java b/hibernate-core/src/test/java/org/hibernate/test/onetoone/optional/BidirectionalOptionalOneToOneTest.java index a074b36f89..f26b2f3d4a 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/onetoone/optional/BidirectionalOptionalOneToOneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/onetoone/optional/BidirectionalOptionalOneToOneTest.java @@ -34,7 +34,6 @@ public class BidirectionalOptionalOneToOneTest } @Test - @FailureExpected( jiraKey = "HHH-9460" ) public void test() { doInJPA( this::entityManagerFactory, entityManager -> {