Use FK descriptor instead of target entity identifier

This commit is contained in:
Christian Beikov 2021-03-10 19:37:23 +01:00
parent c58227241f
commit 06d2a0c23e
9 changed files with 45 additions and 33 deletions

View File

@ -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,

View File

@ -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);

View File

@ -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 {

View File

@ -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();

View File

@ -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 );
}

View File

@ -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 ) {

View File

@ -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

View File

@ -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,

View File

@ -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 {