Fix foreign key direction issues
This commit is contained in:
parent
0157af79f7
commit
e122ac33dc
|
@ -90,6 +90,7 @@ import org.hibernate.type.CollectionType;
|
||||||
import org.hibernate.type.ComponentType;
|
import org.hibernate.type.ComponentType;
|
||||||
import org.hibernate.type.CompositeType;
|
import org.hibernate.type.CompositeType;
|
||||||
import org.hibernate.type.EntityType;
|
import org.hibernate.type.EntityType;
|
||||||
|
import org.hibernate.type.ForeignKeyDirection;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan;
|
import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
@ -969,8 +970,10 @@ public class MappingModelCreationHelper {
|
||||||
.getEntityPersister( bootValueMapping.getReferencedEntityName() );
|
.getEntityPersister( bootValueMapping.getReferencedEntityName() );
|
||||||
|
|
||||||
String referencedPropertyName;
|
String referencedPropertyName;
|
||||||
|
boolean swapDirection = false;
|
||||||
if ( bootValueMapping instanceof OneToOne ) {
|
if ( bootValueMapping instanceof OneToOne ) {
|
||||||
OneToOne oneToOne = (OneToOne) bootValueMapping;
|
OneToOne oneToOne = (OneToOne) bootValueMapping;
|
||||||
|
swapDirection = oneToOne.getForeignKeyType() == ForeignKeyDirection.TO_PARENT;
|
||||||
referencedPropertyName = oneToOne.getMappedByProperty();
|
referencedPropertyName = oneToOne.getMappedByProperty();
|
||||||
if ( referencedPropertyName == null ) {
|
if ( referencedPropertyName == null ) {
|
||||||
referencedPropertyName = oneToOne.getReferencedPropertyName();
|
referencedPropertyName = oneToOne.getReferencedPropertyName();
|
||||||
|
@ -1054,7 +1057,8 @@ public class MappingModelCreationHelper {
|
||||||
keySelectableMapping,
|
keySelectableMapping,
|
||||||
simpleFkTarget,
|
simpleFkTarget,
|
||||||
(owner) -> ( (PropertyBasedMapping) simpleFkTarget ).getPropertyAccess().getGetter().get( owner ),
|
(owner) -> ( (PropertyBasedMapping) simpleFkTarget ).getPropertyAccess().getGetter().get( owner ),
|
||||||
bootValueMapping.isReferenceToPrimaryKey()
|
bootValueMapping.isReferenceToPrimaryKey(),
|
||||||
|
swapDirection
|
||||||
);
|
);
|
||||||
attributeMapping.setForeignKeyDescriptor( foreignKeyDescriptor );
|
attributeMapping.setForeignKeyDescriptor( foreignKeyDescriptor );
|
||||||
}
|
}
|
||||||
|
@ -1062,6 +1066,7 @@ public class MappingModelCreationHelper {
|
||||||
final EmbeddedForeignKeyDescriptor embeddedForeignKeyDescriptor = buildEmbeddableForeignKeyDescriptor(
|
final EmbeddedForeignKeyDescriptor embeddedForeignKeyDescriptor = buildEmbeddableForeignKeyDescriptor(
|
||||||
(EmbeddableValuedModelPart) fkTarget,
|
(EmbeddableValuedModelPart) fkTarget,
|
||||||
bootValueMapping,
|
bootValueMapping,
|
||||||
|
swapDirection,
|
||||||
dialect,
|
dialect,
|
||||||
creationProcess
|
creationProcess
|
||||||
);
|
);
|
||||||
|
|
|
@ -68,12 +68,31 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
|
||||||
BasicValuedModelPart targetModelPart,
|
BasicValuedModelPart targetModelPart,
|
||||||
Function<Object, Object> disassemblyValueExtractor,
|
Function<Object, Object> disassemblyValueExtractor,
|
||||||
boolean refersToPrimaryKey) {
|
boolean refersToPrimaryKey) {
|
||||||
|
this( keySelectableMapping, targetModelPart, disassemblyValueExtractor, refersToPrimaryKey, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
public SimpleForeignKeyDescriptor(
|
||||||
|
SelectableMapping keySelectableMapping,
|
||||||
|
BasicValuedModelPart targetModelPart,
|
||||||
|
Function<Object, Object> disassemblyValueExtractor,
|
||||||
|
boolean refersToPrimaryKey,
|
||||||
|
boolean swapDirection) {
|
||||||
assert keySelectableMapping != null;
|
assert keySelectableMapping != null;
|
||||||
assert targetModelPart != null;
|
assert targetModelPart != null;
|
||||||
assert disassemblyValueExtractor != null;
|
assert disassemblyValueExtractor != null;
|
||||||
|
|
||||||
this.keySide = BasicAttributeMapping.withSelectableMapping( targetModelPart, keySelectableMapping );
|
final BasicValuedModelPart keyModelPart = BasicAttributeMapping.withSelectableMapping(
|
||||||
this.targetSide = targetModelPart;
|
targetModelPart,
|
||||||
|
keySelectableMapping
|
||||||
|
);
|
||||||
|
if ( swapDirection ) {
|
||||||
|
this.keySide = targetModelPart;
|
||||||
|
this.targetSide = keyModelPart;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.keySide = keyModelPart;
|
||||||
|
this.targetSide = targetModelPart;
|
||||||
|
}
|
||||||
this.disassemblyValueExtractor = disassemblyValueExtractor;
|
this.disassemblyValueExtractor = disassemblyValueExtractor;
|
||||||
this.refersToPrimaryKey = refersToPrimaryKey;
|
this.refersToPrimaryKey = refersToPrimaryKey;
|
||||||
}
|
}
|
||||||
|
|
|
@ -646,7 +646,7 @@ public class ToOneAttributeMapping
|
||||||
else {
|
else {
|
||||||
// case 1.1
|
// case 1.1
|
||||||
keyResult = foreignKeyDescriptor.createDomainResult( fetchablePath, parentTableGroup, isKeyReferringSide, creationState );
|
keyResult = foreignKeyDescriptor.createDomainResult( fetchablePath, parentTableGroup, isKeyReferringSide, creationState );
|
||||||
selectByUniqueKey = true;
|
selectByUniqueKey = bidirectionalAttributeName != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( fetchTiming == FetchTiming.IMMEDIATE ) {
|
if ( fetchTiming == FetchTiming.IMMEDIATE ) {
|
||||||
|
|
|
@ -10,6 +10,7 @@ import org.hibernate.LockMode;
|
||||||
import org.hibernate.engine.FetchTiming;
|
import org.hibernate.engine.FetchTiming;
|
||||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||||
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||||
|
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
|
||||||
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
|
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
import org.hibernate.sql.results.graph.AbstractFetchParent;
|
import org.hibernate.sql.results.graph.AbstractFetchParent;
|
||||||
|
@ -67,7 +68,7 @@ public class EmbeddableForeignKeyResultImpl<T>
|
||||||
final ToOneAttributeMapping toOne = (ToOneAttributeMapping) fetchable;
|
final ToOneAttributeMapping toOne = (ToOneAttributeMapping) fetchable;
|
||||||
shouldSelect = selected && !creationState.isAssociationKeyVisited(
|
shouldSelect = selected && !creationState.isAssociationKeyVisited(
|
||||||
toOne.getForeignKeyDescriptor().getAssociationKey()
|
toOne.getForeignKeyDescriptor().getAssociationKey()
|
||||||
);
|
) && !ForeignKeyDescriptor.PART_NAME.equals( getNavigablePath().getLocalName() );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
shouldSelect = selected;
|
shouldSelect = selected;
|
||||||
|
|
|
@ -64,56 +64,14 @@ public class EagerKeyManyToOneTest {
|
||||||
scope.inTransaction(
|
scope.inTransaction(
|
||||||
session -> {
|
session -> {
|
||||||
try {
|
try {
|
||||||
/*
|
|
||||||
select
|
|
||||||
card0_.id as id1_0_0_,
|
|
||||||
card0_.field_card_id as field_ca2_0_0_,
|
|
||||||
card0_."field_key_id" as field_ke3_0_0_,
|
|
||||||
cardfield1_.card_id as card_id1_1_1_,
|
|
||||||
cardfield1_."key_id" as key_id2_1_1_,
|
|
||||||
card2_.id as id1_0_2_,
|
|
||||||
card2_.field_card_id as field_ca2_0_2_,
|
|
||||||
card2_."field_key_id" as field_ke3_0_2_,
|
|
||||||
key3_.id as id1_2_3_
|
|
||||||
from
|
|
||||||
Card card0_
|
|
||||||
left outer join
|
|
||||||
CardField cardfield1_
|
|
||||||
on card0_.field_card_id=cardfield1_.card_id
|
|
||||||
and card0_."field_key_id"=cardfield1_."key_id"
|
|
||||||
left outer join
|
|
||||||
Card card2_
|
|
||||||
on cardfield1_.card_id=card2_.id
|
|
||||||
left outer join
|
|
||||||
"key" key3_
|
|
||||||
on cardfield1_."key_id"=key3_.id
|
|
||||||
where
|
|
||||||
card0_.id=?
|
|
||||||
11:08:42,367 TRACE BasicBinder:64 - binding parameter [1] as [VARCHAR] - [cardId]
|
|
||||||
11:08:42,370 TRACE BasicExtractor:60 - extracted value ([id1_0_2_] : [VARCHAR]) - [cardId]
|
|
||||||
11:08:42,370 TRACE BasicExtractor:60 - extracted value ([id1_2_3_] : [VARCHAR]) - [keyId]
|
|
||||||
11:08:42,370 TRACE BasicExtractor:60 - extracted value ([card_id1_1_1_] : [VARCHAR]) - [cardId]
|
|
||||||
11:08:42,370 TRACE BasicExtractor:60 - extracted value ([key_id2_1_1_] : [VARCHAR]) - [keyId]
|
|
||||||
11:08:42,371 TRACE BasicExtractor:60 - extracted value ([field_ca2_0_2_] : [VARCHAR]) - [cardId]
|
|
||||||
11:08:42,372 TRACE BasicExtractor:60 - extracted value ([field_ke3_0_2_] : [VARCHAR]) - [keyId]
|
|
||||||
11:08:42,372 DEBUG SQL:144 -
|
|
||||||
select
|
|
||||||
key0_.id as id1_2_0_
|
|
||||||
from
|
|
||||||
"key" key0_
|
|
||||||
where
|
|
||||||
key0_.id=?
|
|
||||||
11:08:42,372 TRACE BasicBinder:64 - binding parameter [1] as [VARCHAR] - [keyId]
|
|
||||||
|
|
||||||
*/
|
|
||||||
Card card = session.get( Card.class, CARD_ID );
|
Card card = session.get( Card.class, CARD_ID );
|
||||||
|
|
||||||
CardField cf = card.getField();
|
CardField cf = card.getField();
|
||||||
assertSame( card, cf.getPrimaryKey().getCard() );
|
assertSame( card, cf.getPrimaryKey().getCard() );
|
||||||
|
|
||||||
statementInspector.assertExecutedCount( 2 );
|
statementInspector.assertExecutedCount( 2 );
|
||||||
// Since CardField and Key have no additional state, it's not necessary to join their tables
|
// Since Key have no additional state, it's not necessary to join their tables
|
||||||
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 1 );
|
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 2 );
|
||||||
statementInspector.assertNumberOfOccurrenceInQuery( 1, "join", 0 );
|
statementInspector.assertNumberOfOccurrenceInQuery( 1, "join", 0 );
|
||||||
}
|
}
|
||||||
catch (StackOverflowError soe) {
|
catch (StackOverflowError soe) {
|
||||||
|
|
|
@ -82,7 +82,7 @@ public class LazyManyToOneEmbeddedIdWithToOneFKTest {
|
||||||
System system = session.get( System.class, 1 );
|
System system = session.get( System.class, 1 );
|
||||||
assertThat( system, is( notNullValue() ) );
|
assertThat( system, is( notNullValue() ) );
|
||||||
|
|
||||||
statementInspector.assertExecutedCount( 1 );
|
statementInspector.assertExecutedCount( 2 );
|
||||||
|
|
||||||
assertThat( system.getId(), is( 1 ) );
|
assertThat( system.getId(), is( 1 ) );
|
||||||
|
|
||||||
|
@ -98,8 +98,9 @@ public class LazyManyToOneEmbeddedIdWithToOneFKTest {
|
||||||
SystemUser user = system.getUser();
|
SystemUser user = system.getUser();
|
||||||
assertThat( user, is( notNullValue() ) );
|
assertThat( user, is( notNullValue() ) );
|
||||||
|
|
||||||
statementInspector.assertExecutedCount( 1 );
|
statementInspector.assertExecutedCount( 2 );
|
||||||
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 1 );
|
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 0 );
|
||||||
|
statementInspector.assertNumberOfOccurrenceInQuery( 1, "join", 0 );
|
||||||
|
|
||||||
statementInspector.clear();
|
statementInspector.clear();
|
||||||
assertThat( user.getName(), is( "Fab" ) );
|
assertThat( user.getName(), is( "Fab" ) );
|
||||||
|
|
Loading…
Reference in New Issue