HHH-15767 put unique constraints where they belong on optional @OneToOne associations

this was a bug that allowed people to use @OneToOne as a regular @ManyToOne
and ... people did ... as evidenced by all these bogus tests I just fixed

this is in principle a breaking change because it breaks code that was broken
This commit is contained in:
Gavin 2022-11-26 14:43:26 +01:00 committed by Gavin King
parent 82e42ef946
commit 0253e1fe7a
12 changed files with 48 additions and 53 deletions

View File

@ -241,36 +241,32 @@ public class OneToOneSecondPass implements SecondPass {
// if not, then we need to create a many to one and formula
// but actually, since entities linked by a one to one need
// to share the same composite id class, this cannot happen
boolean rightOrder = true;
if ( rightOrder ) {
final ToOneFkSecondPass secondPass = new ToOneFkSecondPass(
oneToOne,
joinColumns,
!optional, //cannot have nullable and unique on certain DBs
propertyHolder.getPersistentClass(),
qualify( propertyHolder.getPath(), propertyName),
buildingContext
);
secondPass.doSecondPass(persistentClasses);
//no column associated since it's a one to one
propertyHolder.addProperty( property, inferredData.getDeclaringClass() );
}
// boolean rightOrder = true;
//
// if ( rightOrder ) {
final ToOneFkSecondPass secondPass = new ToOneFkSecondPass(
oneToOne,
joinColumns,
true,
propertyHolder.getPersistentClass(),
qualify( propertyHolder.getPath(), propertyName),
buildingContext
);
secondPass.doSecondPass(persistentClasses);
//no column associated since it's a one to one
propertyHolder.addProperty( property, inferredData.getDeclaringClass() );
// }
// else {
// this is a @ManyToOne with Formula
// }
}
/**
* Builds the <code>Join</code> instance for the mapped by side of a <i>OneToOne</i> association using
* a join table.
* <p>
* Note:<br/>
* <ul>
* <li>From the mappedBy side we should not create the PK nor the FK, this is handled from the other side.</li>
* <li>This method is a dirty dupe of EntityBinder.bindSecondaryTable</li>.
* </ul>
* </p>
* Builds the {@link Join} instance for the unowned side
* of a {@code OneToOne} association using a join table.
* From the {@code mappedBy} side we should not create
* neither the PK, nor the FK, this is all handled from
* the owning side.
*/
private Join buildJoinFromMappedBySide(PersistentClass persistentClass, Property otherSideProperty, Join originalJoin) {
Join join = new Join();

View File

@ -179,7 +179,7 @@ public class ToOneBinder {
final FkSecondPass secondPass = new ToOneFkSecondPass(
value,
joinColumns,
!optional && unique, //cannot have nullable and unique on certain DBs like Derby
unique,
propertyHolder.getPersistentClass(),
fullPath,
context

View File

@ -61,15 +61,13 @@ public class MappedByEmbeddableTest extends BaseCoreFunctionalTestCase {
Contained contained2 = embed2.getContained();
// switch associations: 1:1 2:2 -> 1:2 2:1
contained1.setContaining( null );
embed2.setContained( null );
session.flush();
embed1.setContained( contained2 );
contained2.setContaining( containing1 );
embed2.setContained( contained1 );
contained1.setContaining( containing2 );
session.update( containing1 );
session.update( containing2 );
session.update( contained1 );
session.update( contained2 );
} );
inTransaction( session -> {

View File

@ -16,9 +16,7 @@ import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import jakarta.persistence.CascadeType;
@ -225,10 +223,10 @@ public class SingleTableInheritancePersistTest {
private String favouriteToy;
@OneToOne
@ManyToOne
private Woman mother;
@OneToOne
@ManyToOne
private Man father;
public Child() {

View File

@ -206,10 +206,10 @@ public class TablePerClassInheritancePersistTest {
private String favouriteToy;
@OneToOne
@ManyToOne
private Woman mother;
@OneToOne
@ManyToOne
private Man father;
public Child() {

View File

@ -16,6 +16,7 @@ import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Inheritance;
import jakarta.persistence.InheritanceType;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OneToOne;
@ -166,10 +167,10 @@ public class TablePerClassInheritanceTest {
private String favouriteToy;
@OneToOne
@ManyToOne
private Woman mother;
@OneToOne
@ManyToOne
private Man father;
public Child() {

View File

@ -77,12 +77,9 @@ public class InsertOrderingSelfReferenceSingleTableInheritance {
@Test
public void test2(EntityManagerFactoryScope scope) {
scope.inTransaction( entityManager -> {
NodeLongValue aparam = new NodeLongValue();
aparam.setLongValue( 123L );
ContentNode xa = new ContentNode( aparam, null, null );
ContentNode xb = new ContentNode( aparam, null, null );
ContentNode xc = new ContentNode( aparam, xb, null );
ContentNode xa = new ContentNode(new NodeLongValue(123L), null, null );
ContentNode xb = new ContentNode(new NodeLongValue(123L), null, null );
ContentNode xc = new ContentNode(new NodeLongValue(123L), xb, null );
NodeLink nl = new NodeLink( xc );
@ -118,8 +115,9 @@ public class InsertOrderingSelfReferenceSingleTableInheritance {
NodeStringValue stringVal = new NodeStringValue();
stringVal.setStringValue( "Node 123" );
ContentNode cn0 = new ContentNode( null, null, null );
ContentNode cn1 = new ContentNode( stringVal, null, null );
ContentNode cn2 = new ContentNode( longVal, cn1, null );
ContentNode cn2 = new ContentNode( longVal, cn0, null );
ContentNode cn3 = new ContentNode( null, cn1, cn2 );
@ -345,6 +343,11 @@ public class InsertOrderingSelfReferenceSingleTableInheritance {
this.longValue = longValue;
}
public NodeLongValue(Long longValue) {
super();
this.longValue = longValue;
}
public NodeLongValue() {
super();
}

View File

@ -54,7 +54,7 @@ public class NullablePrimaryKeyTest {
metadata,
false
);
String expectedMappingTableSql = "create table personAddress (address_id bigint, " +
String expectedMappingTableSql = "create table personAddress (address_id bigint unique, " +
"person_id bigint not null, primary key (person_id))";
assertEquals( "Wrong SQL", expectedMappingTableSql, commands.get( 2 ) );

View File

@ -120,7 +120,7 @@ public class ToOneOnDeleteTest {
private String name;
@OneToOne
@ManyToOne
@OnDelete(action = OnDeleteAction.CASCADE)
private Child parent;
}

View File

@ -13,7 +13,6 @@ import jakarta.persistence.Id;
import jakarta.persistence.Inheritance;
import jakarta.persistence.InheritanceType;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToOne;
import jakarta.persistence.criteria.JoinType;
import org.hibernate.envers.Audited;
@ -131,7 +130,7 @@ public class InheritanceAssociationToOneInnerJoinTest extends BaseEnversJPAFunct
public static class EntityA {
@Id
private Integer id;
@OneToOne
@ManyToOne
private EntityD relationToD;
@ManyToOne
private EntityC relationToC;

View File

@ -8,7 +8,7 @@ package org.hibernate.orm.test.envers.integration.onetoone.bidirectional;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.OneToOne;
import jakarta.persistence.ManyToOne;
import org.hibernate.envers.Audited;
@ -24,7 +24,7 @@ public class BiRefIngEntity {
private String data;
@Audited
@OneToOne
@ManyToOne
private BiRefEdEntity reference;
public BiRefIngEntity() {

View File

@ -8,7 +8,7 @@ package org.hibernate.orm.test.envers.integration.onetoone.unidirectional;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.OneToOne;
import jakarta.persistence.ManyToOne;
import org.hibernate.envers.Audited;
@ -26,7 +26,7 @@ public class UniRefIngEntity {
private String data;
@Audited
@OneToOne
@ManyToOne
private UniRefEdEntity reference;
public UniRefIngEntity() {