From 06d2a0c23ec95ab6078d81abc674886a47fbf98e Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Wed, 10 Mar 2021 19:37:23 +0100 Subject: [PATCH] Use FK descriptor instead of target entity identifier --- .../AbstractCompositeIdentifierMapping.java | 10 ++++------ .../mapping/ForeignKeyDescriptor.java | 3 +++ .../internal/CompoundNaturalIdMapping.java | 6 +----- .../EmbeddedForeignKeyDescriptor.java | 10 ++++++++++ .../internal/MappingModelCreationHelper.java | 9 ++++++--- .../internal/PluralAttributeMappingImpl.java | 3 ++- .../internal/SimpleForeignKeyDescriptor.java | 19 +++++++++++++++++-- .../internal/ToOneAttributeMapping.java | 2 +- .../hibernate/query/sqm/internal/SqmUtil.java | 16 +--------------- 9 files changed, 45 insertions(+), 33 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AbstractCompositeIdentifierMapping.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AbstractCompositeIdentifierMapping.java index 69f8ef565c..55c264bd4c 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AbstractCompositeIdentifierMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AbstractCompositeIdentifierMapping.java @@ -16,6 +16,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.metamodel.mapping.AttributeMapping; +import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; import org.hibernate.metamodel.mapping.SelectionConsumer; import org.hibernate.metamodel.mapping.SelectionMappings; import org.hibernate.metamodel.mapping.CompositeIdentifierMapping; @@ -202,12 +203,9 @@ public abstract class AbstractCompositeIdentifierMapping final AttributeMapping attributeMapping = attributeMappings.get( i ); final Object o = attributeMapping.getPropertyAccess().getGetter().get( value ); if ( attributeMapping instanceof ToOneAttributeMapping ) { - final EntityMappingType associatedEntityMappingType = - ( (ToOneAttributeMapping) attributeMapping ).getAssociatedEntityMappingType(); - final EntityIdentifierMapping identifierMapping = - associatedEntityMappingType.getIdentifierMapping(); - final Object identifier = identifierMapping.getIdentifier( o, session ); - span += identifierMapping.forEachJdbcValue( + final ForeignKeyDescriptor fkDescriptor = ( (ToOneAttributeMapping) attributeMapping ).getForeignKeyDescriptor(); + final Object identifier = fkDescriptor.getAssociationKeyFromTarget( o, session ); + span += fkDescriptor.forEachJdbcValue( identifier, clause, span + offset, diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ForeignKeyDescriptor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ForeignKeyDescriptor.java index 614dd54b04..dd5c9ca7a4 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ForeignKeyDescriptor.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ForeignKeyDescriptor.java @@ -6,6 +6,7 @@ */ package org.hibernate.metamodel.mapping; +import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.query.NavigablePath; import org.hibernate.sql.ast.SqlAstJoinType; import org.hibernate.sql.ast.spi.SqlAstCreationContext; @@ -65,6 +66,8 @@ public interface ForeignKeyDescriptor extends VirtualModelPart { return visitReferringColumns( offset, consumer ); } + Object getAssociationKeyFromTarget(Object targetObject, SharedSessionContractImplementor session); + int visitReferringColumns(int offset, SelectionConsumer consumer); int visitTargetColumns(int offset, SelectionConsumer consumer); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/CompoundNaturalIdMapping.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/CompoundNaturalIdMapping.java index ee1efb7eb7..32d99351df 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/CompoundNaturalIdMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/CompoundNaturalIdMapping.java @@ -331,11 +331,7 @@ public class CompoundNaturalIdMapping extends AbstractNaturalIdMapping implement if ( attributeMapping instanceof ToOneAttributeMapping ) { final ToOneAttributeMapping toOne = (ToOneAttributeMapping) attributeMapping; final ForeignKeyDescriptor fKDescriptor = toOne.getForeignKeyDescriptor(); - - final EntityMappingType associatedEntityMapping = toOne.getEntityMappingType(); - final EntityIdentifierMapping associatedEntityMappingIdentifierMapping = associatedEntityMapping.getIdentifierMapping(); - - final Object keyValue = value == null ? null : associatedEntityMappingIdentifierMapping.getIdentifier( value, session ); + final Object keyValue = value == null ? null : fKDescriptor.disassemble( value, session ); fKDescriptor.breakDownJdbcValues( keyValue, valueConsumer, session ); } else { diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EmbeddedForeignKeyDescriptor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EmbeddedForeignKeyDescriptor.java index cbc5570fe5..429acad1aa 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EmbeddedForeignKeyDescriptor.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EmbeddedForeignKeyDescriptor.java @@ -409,6 +409,16 @@ public class EmbeddedForeignKeyDescriptor implements ForeignKeyDescriptor, Model ); } + @Override + public Object getAssociationKeyFromTarget(Object targetObject, SharedSessionContractImplementor session) { + // If the mapping type has an identifier type, that identifier is the key + if ( mappingType instanceof SingleAttributeIdentifierMapping ) { + return ( (SingleAttributeIdentifierMapping) mappingType ).getIdentifier( targetObject, session ); + } + // Otherwise this is a key based on the target object i.e. without id-class + return targetObject; + } + @Override public EntityMappingType findContainingEntityMapping() { throw new UnsupportedOperationException(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/MappingModelCreationHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/MappingModelCreationHelper.java index 5d85bec4f3..2cb43f2287 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/MappingModelCreationHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/MappingModelCreationHelper.java @@ -899,7 +899,8 @@ public class MappingModelCreationHelper { final Type keyType = bootValueMappingKey.getType(); final ModelPart fkTarget; final String lhsPropertyName = collectionDescriptor.getCollectionType().getLHSPropertyName(); - if ( lhsPropertyName == null ) { + final boolean isReferenceToPrimaryKey = lhsPropertyName == null; + if ( isReferenceToPrimaryKey ) { fkTarget = collectionDescriptor.getOwnerEntityPersister().getIdentifierMapping(); } else { @@ -922,7 +923,8 @@ public class MappingModelCreationHelper { new SimpleForeignKeyDescriptor( keySelectionMapping, simpleFkTarget, - ( (PropertyBasedMapping) simpleFkTarget ).getPropertyAccess() + ( (PropertyBasedMapping) simpleFkTarget ).getPropertyAccess(), + isReferenceToPrimaryKey ) ); } @@ -1045,7 +1047,8 @@ public class MappingModelCreationHelper { final ForeignKeyDescriptor foreignKeyDescriptor = new SimpleForeignKeyDescriptor( keySelectionMapping, simpleFkTarget, - ( (PropertyBasedMapping) simpleFkTarget ).getPropertyAccess() + ( (PropertyBasedMapping) simpleFkTarget ).getPropertyAccess(), + bootValueMapping.isReferenceToPrimaryKey() ); attributeMapping.setForeignKeyDescriptor( foreignKeyDescriptor ); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/PluralAttributeMappingImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/PluralAttributeMappingImpl.java index 0304a328eb..f2b7e8e193 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/PluralAttributeMappingImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/PluralAttributeMappingImpl.java @@ -342,7 +342,8 @@ public class PluralAttributeMappingImpl return new SimpleForeignKeyDescriptor( keySelectionMapping, basicFkTargetPart, - ( (PropertyBasedMapping) basicFkTargetPart ).getPropertyAccess() + ( (PropertyBasedMapping) basicFkTargetPart ).getPropertyAccess(), + entityType.isReferenceToPrimaryKey() ); } else if ( fkTargetPart instanceof EmbeddableValuedModelPart ) { diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SimpleForeignKeyDescriptor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SimpleForeignKeyDescriptor.java index 3f8e0c3866..374e4daab8 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SimpleForeignKeyDescriptor.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SimpleForeignKeyDescriptor.java @@ -24,6 +24,7 @@ import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.MappingType; import org.hibernate.metamodel.model.domain.NavigableRole; import org.hibernate.property.access.spi.PropertyAccess; +import org.hibernate.proxy.HibernateProxy; import org.hibernate.query.ComparisonOperator; import org.hibernate.query.NavigablePath; import org.hibernate.sql.ast.Clause; @@ -53,15 +54,18 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa private final SelectionMapping keySelectionMapping; private final SelectionMapping targetSelectionMapping; private final PropertyAccess propertyAccess; + private final boolean refersToPrimaryKey; private AssociationKey associationKey; public SimpleForeignKeyDescriptor( SelectionMapping keySelectionMapping, SelectionMapping targetSelectionMapping, - PropertyAccess propertyAccess) { + PropertyAccess propertyAccess, + boolean refersToPrimaryKey) { this.keySelectionMapping = keySelectionMapping; this.targetSelectionMapping = targetSelectionMapping; this.propertyAccess = propertyAccess; + this.refersToPrimaryKey = refersToPrimaryKey; } @Override @@ -264,7 +268,18 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa @Override public Object disassemble(Object value, SharedSessionContractImplementor session) { - return value == null ? null : propertyAccess.getGetter().get( value ); + if ( value == null ) { + return null; + } + if ( refersToPrimaryKey && value instanceof HibernateProxy ) { + return ( (HibernateProxy) value ).getHibernateLazyInitializer().getIdentifier(); + } + return propertyAccess.getGetter().get( value ); + } + + @Override + public Object getAssociationKeyFromTarget(Object targetObject, SharedSessionContractImplementor session) { + return disassemble( targetObject, session ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java index 6aca968aad..4b4cf1dee1 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java @@ -698,7 +698,7 @@ public class ToOneAttributeMapping @Override public int forEachJdbcValue(Object value, Clause clause, int offset, JdbcValuesConsumer consumer, SharedSessionContractImplementor session) { - return foreignKeyDescriptor.forEachJdbcValue( + return foreignKeyDescriptor.forEachDisassembledJdbcValue( foreignKeyDescriptor.disassemble( value, session ), clause, offset, diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmUtil.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmUtil.java index d1c3188f86..bf90334eb9 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmUtil.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmUtil.java @@ -18,9 +18,7 @@ import java.util.function.Function; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.metamodel.MappingMetamodel; -import org.hibernate.metamodel.mapping.Bindable; import org.hibernate.metamodel.mapping.EntityIdentifierMapping; -import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.MappingModelExpressable; import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; import org.hibernate.metamodel.model.domain.AllowableParameterType; @@ -288,19 +286,7 @@ public class SqmUtil { } else if ( type instanceof ToOneAttributeMapping ) { ToOneAttributeMapping association = (ToOneAttributeMapping) type; - if ( association.getReferencedPropertyName() == null ) { - bindValue = association.getEntityMappingType().getIdentifierMapping().getIdentifier( - bindValue, - session - ); - } - else { - bindValue = association.getEntityMappingType() - .findAttributeMapping( association.getReferencedPropertyName() ) - .getPropertyAccess() - .getGetter() - .get( bindValue ); - } + bindValue = association.getForeignKeyDescriptor().getAssociationKeyFromTarget( bindValue, session ); mappingExpressable = association.getForeignKeyDescriptor(); } else {