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:
parent
82e42ef946
commit
0253e1fe7a
|
@ -241,36 +241,32 @@ public class OneToOneSecondPass implements SecondPass {
|
||||||
// if not, then we need to create a many to one and formula
|
// if not, then we need to create a many to one and formula
|
||||||
// but actually, since entities linked by a one to one need
|
// but actually, since entities linked by a one to one need
|
||||||
// to share the same composite id class, this cannot happen
|
// to share the same composite id class, this cannot happen
|
||||||
boolean rightOrder = true;
|
// boolean rightOrder = true;
|
||||||
|
//
|
||||||
if ( rightOrder ) {
|
// if ( rightOrder ) {
|
||||||
final ToOneFkSecondPass secondPass = new ToOneFkSecondPass(
|
final ToOneFkSecondPass secondPass = new ToOneFkSecondPass(
|
||||||
oneToOne,
|
oneToOne,
|
||||||
joinColumns,
|
joinColumns,
|
||||||
!optional, //cannot have nullable and unique on certain DBs
|
true,
|
||||||
propertyHolder.getPersistentClass(),
|
propertyHolder.getPersistentClass(),
|
||||||
qualify( propertyHolder.getPath(), propertyName),
|
qualify( propertyHolder.getPath(), propertyName),
|
||||||
buildingContext
|
buildingContext
|
||||||
);
|
);
|
||||||
secondPass.doSecondPass(persistentClasses);
|
secondPass.doSecondPass(persistentClasses);
|
||||||
//no column associated since it's a one to one
|
//no column associated since it's a one to one
|
||||||
propertyHolder.addProperty( property, inferredData.getDeclaringClass() );
|
propertyHolder.addProperty( property, inferredData.getDeclaringClass() );
|
||||||
}
|
// }
|
||||||
// else {
|
// else {
|
||||||
// this is a @ManyToOne with Formula
|
// this is a @ManyToOne with Formula
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds the <code>Join</code> instance for the mapped by side of a <i>OneToOne</i> association using
|
* Builds the {@link Join} instance for the unowned side
|
||||||
* a join table.
|
* of a {@code OneToOne} association using a join table.
|
||||||
* <p>
|
* From the {@code mappedBy} side we should not create
|
||||||
* Note:<br/>
|
* neither the PK, nor the FK, this is all handled from
|
||||||
* <ul>
|
* the owning side.
|
||||||
* <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>
|
|
||||||
*/
|
*/
|
||||||
private Join buildJoinFromMappedBySide(PersistentClass persistentClass, Property otherSideProperty, Join originalJoin) {
|
private Join buildJoinFromMappedBySide(PersistentClass persistentClass, Property otherSideProperty, Join originalJoin) {
|
||||||
Join join = new Join();
|
Join join = new Join();
|
||||||
|
|
|
@ -179,7 +179,7 @@ public class ToOneBinder {
|
||||||
final FkSecondPass secondPass = new ToOneFkSecondPass(
|
final FkSecondPass secondPass = new ToOneFkSecondPass(
|
||||||
value,
|
value,
|
||||||
joinColumns,
|
joinColumns,
|
||||||
!optional && unique, //cannot have nullable and unique on certain DBs like Derby
|
unique,
|
||||||
propertyHolder.getPersistentClass(),
|
propertyHolder.getPersistentClass(),
|
||||||
fullPath,
|
fullPath,
|
||||||
context
|
context
|
||||||
|
|
|
@ -61,15 +61,13 @@ public class MappedByEmbeddableTest extends BaseCoreFunctionalTestCase {
|
||||||
Contained contained2 = embed2.getContained();
|
Contained contained2 = embed2.getContained();
|
||||||
|
|
||||||
// switch associations: 1:1 2:2 -> 1:2 2:1
|
// switch associations: 1:1 2:2 -> 1:2 2:1
|
||||||
|
contained1.setContaining( null );
|
||||||
|
embed2.setContained( null );
|
||||||
|
session.flush();
|
||||||
embed1.setContained( contained2 );
|
embed1.setContained( contained2 );
|
||||||
contained2.setContaining( containing1 );
|
contained2.setContaining( containing1 );
|
||||||
embed2.setContained( contained1 );
|
embed2.setContained( contained1 );
|
||||||
contained1.setContaining( containing2 );
|
contained1.setContaining( containing2 );
|
||||||
|
|
||||||
session.update( containing1 );
|
|
||||||
session.update( containing2 );
|
|
||||||
session.update( contained1 );
|
|
||||||
session.update( contained2 );
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
inTransaction( session -> {
|
inTransaction( session -> {
|
||||||
|
|
|
@ -16,9 +16,7 @@ import org.hibernate.testing.TestForIssue;
|
||||||
import org.hibernate.testing.orm.junit.DomainModel;
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import jakarta.persistence.CascadeType;
|
import jakarta.persistence.CascadeType;
|
||||||
|
@ -225,10 +223,10 @@ public class SingleTableInheritancePersistTest {
|
||||||
|
|
||||||
private String favouriteToy;
|
private String favouriteToy;
|
||||||
|
|
||||||
@OneToOne
|
@ManyToOne
|
||||||
private Woman mother;
|
private Woman mother;
|
||||||
|
|
||||||
@OneToOne
|
@ManyToOne
|
||||||
private Man father;
|
private Man father;
|
||||||
|
|
||||||
public Child() {
|
public Child() {
|
||||||
|
|
|
@ -206,10 +206,10 @@ public class TablePerClassInheritancePersistTest {
|
||||||
|
|
||||||
private String favouriteToy;
|
private String favouriteToy;
|
||||||
|
|
||||||
@OneToOne
|
@ManyToOne
|
||||||
private Woman mother;
|
private Woman mother;
|
||||||
|
|
||||||
@OneToOne
|
@ManyToOne
|
||||||
private Man father;
|
private Man father;
|
||||||
|
|
||||||
public Child() {
|
public Child() {
|
||||||
|
|
|
@ -16,6 +16,7 @@ import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
import jakarta.persistence.Inheritance;
|
import jakarta.persistence.Inheritance;
|
||||||
import jakarta.persistence.InheritanceType;
|
import jakarta.persistence.InheritanceType;
|
||||||
|
import jakarta.persistence.ManyToOne;
|
||||||
import jakarta.persistence.OneToMany;
|
import jakarta.persistence.OneToMany;
|
||||||
import jakarta.persistence.OneToOne;
|
import jakarta.persistence.OneToOne;
|
||||||
|
|
||||||
|
@ -166,10 +167,10 @@ public class TablePerClassInheritanceTest {
|
||||||
|
|
||||||
private String favouriteToy;
|
private String favouriteToy;
|
||||||
|
|
||||||
@OneToOne
|
@ManyToOne
|
||||||
private Woman mother;
|
private Woman mother;
|
||||||
|
|
||||||
@OneToOne
|
@ManyToOne
|
||||||
private Man father;
|
private Man father;
|
||||||
|
|
||||||
public Child() {
|
public Child() {
|
||||||
|
|
|
@ -77,12 +77,9 @@ public class InsertOrderingSelfReferenceSingleTableInheritance {
|
||||||
@Test
|
@Test
|
||||||
public void test2(EntityManagerFactoryScope scope) {
|
public void test2(EntityManagerFactoryScope scope) {
|
||||||
scope.inTransaction( entityManager -> {
|
scope.inTransaction( entityManager -> {
|
||||||
NodeLongValue aparam = new NodeLongValue();
|
ContentNode xa = new ContentNode(new NodeLongValue(123L), null, null );
|
||||||
aparam.setLongValue( 123L );
|
ContentNode xb = new ContentNode(new NodeLongValue(123L), null, null );
|
||||||
|
ContentNode xc = new ContentNode(new NodeLongValue(123L), xb, null );
|
||||||
ContentNode xa = new ContentNode( aparam, null, null );
|
|
||||||
ContentNode xb = new ContentNode( aparam, null, null );
|
|
||||||
ContentNode xc = new ContentNode( aparam, xb, null );
|
|
||||||
|
|
||||||
NodeLink nl = new NodeLink( xc );
|
NodeLink nl = new NodeLink( xc );
|
||||||
|
|
||||||
|
@ -118,8 +115,9 @@ public class InsertOrderingSelfReferenceSingleTableInheritance {
|
||||||
NodeStringValue stringVal = new NodeStringValue();
|
NodeStringValue stringVal = new NodeStringValue();
|
||||||
stringVal.setStringValue( "Node 123" );
|
stringVal.setStringValue( "Node 123" );
|
||||||
|
|
||||||
|
ContentNode cn0 = new ContentNode( null, null, null );
|
||||||
ContentNode cn1 = new ContentNode( stringVal, 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 );
|
ContentNode cn3 = new ContentNode( null, cn1, cn2 );
|
||||||
|
|
||||||
|
@ -345,6 +343,11 @@ public class InsertOrderingSelfReferenceSingleTableInheritance {
|
||||||
this.longValue = longValue;
|
this.longValue = longValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NodeLongValue(Long longValue) {
|
||||||
|
super();
|
||||||
|
this.longValue = longValue;
|
||||||
|
}
|
||||||
|
|
||||||
public NodeLongValue() {
|
public NodeLongValue() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ public class NullablePrimaryKeyTest {
|
||||||
metadata,
|
metadata,
|
||||||
false
|
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))";
|
"person_id bigint not null, primary key (person_id))";
|
||||||
|
|
||||||
assertEquals( "Wrong SQL", expectedMappingTableSql, commands.get( 2 ) );
|
assertEquals( "Wrong SQL", expectedMappingTableSql, commands.get( 2 ) );
|
||||||
|
|
|
@ -120,7 +120,7 @@ public class ToOneOnDeleteTest {
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@OneToOne
|
@ManyToOne
|
||||||
@OnDelete(action = OnDeleteAction.CASCADE)
|
@OnDelete(action = OnDeleteAction.CASCADE)
|
||||||
private Child parent;
|
private Child parent;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@ import jakarta.persistence.Id;
|
||||||
import jakarta.persistence.Inheritance;
|
import jakarta.persistence.Inheritance;
|
||||||
import jakarta.persistence.InheritanceType;
|
import jakarta.persistence.InheritanceType;
|
||||||
import jakarta.persistence.ManyToOne;
|
import jakarta.persistence.ManyToOne;
|
||||||
import jakarta.persistence.OneToOne;
|
|
||||||
import jakarta.persistence.criteria.JoinType;
|
import jakarta.persistence.criteria.JoinType;
|
||||||
|
|
||||||
import org.hibernate.envers.Audited;
|
import org.hibernate.envers.Audited;
|
||||||
|
@ -131,7 +130,7 @@ public class InheritanceAssociationToOneInnerJoinTest extends BaseEnversJPAFunct
|
||||||
public static class EntityA {
|
public static class EntityA {
|
||||||
@Id
|
@Id
|
||||||
private Integer id;
|
private Integer id;
|
||||||
@OneToOne
|
@ManyToOne
|
||||||
private EntityD relationToD;
|
private EntityD relationToD;
|
||||||
@ManyToOne
|
@ManyToOne
|
||||||
private EntityC relationToC;
|
private EntityC relationToC;
|
||||||
|
|
|
@ -8,7 +8,7 @@ package org.hibernate.orm.test.envers.integration.onetoone.bidirectional;
|
||||||
|
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
import jakarta.persistence.OneToOne;
|
import jakarta.persistence.ManyToOne;
|
||||||
|
|
||||||
import org.hibernate.envers.Audited;
|
import org.hibernate.envers.Audited;
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ public class BiRefIngEntity {
|
||||||
private String data;
|
private String data;
|
||||||
|
|
||||||
@Audited
|
@Audited
|
||||||
@OneToOne
|
@ManyToOne
|
||||||
private BiRefEdEntity reference;
|
private BiRefEdEntity reference;
|
||||||
|
|
||||||
public BiRefIngEntity() {
|
public BiRefIngEntity() {
|
||||||
|
|
|
@ -8,7 +8,7 @@ package org.hibernate.orm.test.envers.integration.onetoone.unidirectional;
|
||||||
|
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
import jakarta.persistence.OneToOne;
|
import jakarta.persistence.ManyToOne;
|
||||||
|
|
||||||
import org.hibernate.envers.Audited;
|
import org.hibernate.envers.Audited;
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ public class UniRefIngEntity {
|
||||||
private String data;
|
private String data;
|
||||||
|
|
||||||
@Audited
|
@Audited
|
||||||
@OneToOne
|
@ManyToOne
|
||||||
private UniRefEdEntity reference;
|
private UniRefEdEntity reference;
|
||||||
|
|
||||||
public UniRefIngEntity() {
|
public UniRefIngEntity() {
|
||||||
|
|
Loading…
Reference in New Issue