HHH-15853 Avoid re-computing AttributeMetadataAccess at runtime

This commit is contained in:
Sanne Grinovero 2022-12-08 13:51:09 +00:00 committed by Sanne Grinovero
parent 58f8d3d449
commit d2d40c7318
6 changed files with 201 additions and 355 deletions

View File

@ -12,7 +12,6 @@ package org.hibernate.metamodel.mapping;
*
* @author Steve Ebersole
*/
@FunctionalInterface
public interface AttributeMetadataAccess {
/**
* Resolve the details about the attribute

View File

@ -30,8 +30,6 @@ import org.hibernate.mapping.Selectable;
import org.hibernate.mapping.Value;
import org.hibernate.metamodel.UnsupportedMappingException;
import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.AttributeMetadata;
import org.hibernate.metamodel.mapping.AttributeMetadataAccess;
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
@ -364,48 +362,14 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType
mutabilityPlan = ImmutableMutabilityPlan.INSTANCE;
}
final AttributeMetadataAccess attributeMetadataAccess = entityMappingType -> new AttributeMetadata() {
@Override
public PropertyAccess getPropertyAccess() {
return propertyAccess;
}
@Override
public MutabilityPlan<?> getMutabilityPlan() {
return mutabilityPlan;
}
@Override
public boolean isNullable() {
return nullable;
}
@Override
public boolean isInsertable() {
return insertable;
}
@Override
public boolean isUpdatable() {
return updateable;
}
@Override
public boolean isIncludedInDirtyChecking() {
// todo (6.0) : do not believe this is correct
return updateable;
}
@Override
public boolean isIncludedInOptimisticLocking() {
return includeInOptimisticLocking;
}
@Override
public CascadeStyle getCascadeStyle() {
return cascadeStyle;
}
};
BasicAttributeMetadataAccess attributeMetadataAccess = new BasicAttributeMetadataAccess( propertyAccess,
mutabilityPlan,
nullable,
insertable,
updateable,
includeInOptimisticLocking,
cascadeStyle
);
attributeMapping = new DiscriminatedAssociationAttributeMapping(
navigableRole.append( bootPropertyDescriptor.getName() ),

View File

@ -0,0 +1,123 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.metamodel.mapping.internal;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.CascadeStyles;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.Value;
import org.hibernate.metamodel.mapping.AttributeMetadata;
import org.hibernate.metamodel.mapping.AttributeMetadataAccess;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.type.descriptor.java.MutabilityPlan;
public final class BasicAttributeMetadataAccess implements AttributeMetadataAccess, AttributeMetadata {
private final PropertyAccess propertyAccess;
private final MutabilityPlan<?> mutabilityPlan;
private final boolean nullable;
private final boolean insertable;
private final boolean updateable;
private final boolean includeInOptimisticLocking;
private final CascadeStyle cascadeStyle;
public BasicAttributeMetadataAccess(
PropertyAccess propertyAccess,
MutabilityPlan mutabilityPlan,
Property bootProperty,
Value value
) {
this(
propertyAccess,
mutabilityPlan,
value.isNullable(),
bootProperty.isInsertable(),
bootProperty.isUpdateable(),
bootProperty.isOptimisticLocked()
);
}
public BasicAttributeMetadataAccess(
PropertyAccess propertyAccess,
MutabilityPlan mutabilityPlan,
boolean nullable, boolean insertable, boolean updateable, boolean includeInOptimisticLocking) {
this(
propertyAccess,
mutabilityPlan,
nullable,
insertable,
updateable,
includeInOptimisticLocking,
CascadeStyles.NONE // default - but beware of comment on AttributeMetadata#getCascadeStyle having a TODO
);
}
public BasicAttributeMetadataAccess(
PropertyAccess propertyAccess,
MutabilityPlan mutabilityPlan,
boolean nullable,
boolean insertable,
boolean updateable,
boolean includeInOptimisticLocking,
CascadeStyle cascadeStyle) {
this.propertyAccess = propertyAccess;
this.mutabilityPlan = mutabilityPlan;
this.nullable = nullable;
this.insertable = insertable;
this.updateable = updateable;
this.includeInOptimisticLocking = includeInOptimisticLocking;
this.cascadeStyle = cascadeStyle;
}
@Override
public AttributeMetadata resolveAttributeMetadata(EntityMappingType entityMappingType) {
return this;
}
@Override
public PropertyAccess getPropertyAccess() {
return propertyAccess;
}
@Override
public MutabilityPlan getMutabilityPlan() {
return mutabilityPlan;
}
@Override
public boolean isNullable() {
return nullable;
}
@Override
public boolean isInsertable() {
return insertable;
}
@Override
public boolean isUpdatable() {
return updateable;
}
@Override
public boolean isIncludedInDirtyChecking() {
// todo (6.0) : do not believe this is correct
return updateable;
}
@Override
public boolean isIncludedInOptimisticLocking() {
return includeInOptimisticLocking;
}
@Override
public CascadeStyle getCascadeStyle() {
return cascadeStyle;
}
}

View File

@ -34,8 +34,6 @@ import org.hibernate.mapping.Property;
import org.hibernate.mapping.Selectable;
import org.hibernate.mapping.Value;
import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.AttributeMetadata;
import org.hibernate.metamodel.mapping.AttributeMetadataAccess;
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
import org.hibernate.metamodel.mapping.EntityMappingType;
@ -374,48 +372,15 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme
mutabilityPlan = ImmutableMutabilityPlan.INSTANCE;
}
final AttributeMetadataAccess attributeMetadataAccess = entityMappingType -> new AttributeMetadata() {
@Override
public PropertyAccess getPropertyAccess() {
return propertyAccess;
}
@Override
public MutabilityPlan<?> getMutabilityPlan() {
return mutabilityPlan;
}
@Override
public boolean isNullable() {
return nullable;
}
@Override
public boolean isInsertable() {
return insertable;
}
@Override
public boolean isUpdatable() {
return updateable;
}
@Override
public boolean isIncludedInDirtyChecking() {
// todo (6.0) : do not believe this is correct
return updateable;
}
@Override
public boolean isIncludedInOptimisticLocking() {
return includeInOptimisticLocking;
}
@Override
public CascadeStyle getCascadeStyle() {
return cascadeStyle;
}
};
BasicAttributeMetadataAccess attributeMetadataAccess = new BasicAttributeMetadataAccess(
propertyAccess,
mutabilityPlan,
nullable,
insertable,
updateable,
includeInOptimisticLocking,
cascadeStyle
);
attributeMapping = new DiscriminatedAssociationAttributeMapping(
valueMapping.getNavigableRole().append( bootPropertyDescriptor.getName() ),

View File

@ -50,7 +50,6 @@ import org.hibernate.mapping.ToOne;
import org.hibernate.mapping.Value;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.metamodel.MappingMetamodel;
import org.hibernate.metamodel.mapping.AttributeMetadata;
import org.hibernate.metamodel.mapping.AttributeMetadataAccess;
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
import org.hibernate.metamodel.mapping.CollectionIdentifierDescriptor;
@ -60,7 +59,6 @@ import org.hibernate.metamodel.mapping.CompositeIdentifierMapping;
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.ManagedMappingType;
@ -198,55 +196,7 @@ public class MappingModelCreationHelper {
MappingModelCreationProcess creationProcess) {
final Value value = bootProperty.getValue();
final BasicValue.Resolution<?> resolution = ( (Resolvable) value ).resolve();
final AttributeMetadataAccess attributeMetadataAccess = entityMappingType -> new AttributeMetadata() {
private final MutabilityPlan mutabilityPlan = resolution.getMutabilityPlan();
private final boolean nullable = value.isNullable();
private final boolean insertable = bootProperty.isInsertable();
private final boolean updateable = bootProperty.isUpdateable();
private final boolean includeInOptimisticLocking = bootProperty.isOptimisticLocked();
@Override
public PropertyAccess getPropertyAccess() {
return propertyAccess;
}
@Override
public MutabilityPlan getMutabilityPlan() {
return mutabilityPlan;
}
@Override
public boolean isNullable() {
return nullable;
}
@Override
public boolean isInsertable() {
return insertable;
}
@Override
public boolean isUpdatable() {
return updateable;
}
@Override
public boolean isIncludedInDirtyChecking() {
// todo (6.0) : do not believe this is correct
return updateable;
}
@Override
public boolean isIncludedInOptimisticLocking() {
return includeInOptimisticLocking;
}
@Override
public CascadeStyle getCascadeStyle() {
return cascadeStyle;
}
};
BasicAttributeMetadataAccess attributeMetadataAccess = new BasicAttributeMetadataAccess( propertyAccess, resolution.getMutabilityPlan(), bootProperty, value );
final FetchTiming fetchTiming;
final FetchStyle fetchStyle;
@ -364,145 +314,54 @@ public class MappingModelCreationHelper {
PropertyAccess propertyAccess,
CascadeStyle cascadeStyle,
MappingModelCreationProcess creationProcess) {
return entityMappingType -> new AttributeMetadata() {
private final boolean nullable = bootProperty.getValue().isNullable();
private final boolean insertable = bootProperty.isInsertable();
private final boolean updateable = bootProperty.isUpdateable();
private final boolean includeInOptimisticLocking = bootProperty.isOptimisticLocked();
final MutabilityPlan mutabilityPlan;
if ( bootProperty.isUpdateable() ) {
mutabilityPlan = new MutabilityPlan() {
private final MutabilityPlan mutabilityPlan;
final SessionFactoryImplementor sessionFactory = creationProcess.getCreationContext()
.getSessionFactory();
{
if ( updateable ) {
mutabilityPlan = new MutabilityPlan() {
@Override
public boolean isMutable() {
return true;
}
@Override
public Object deepCopy(Object value) {
if ( value == null ) {
return null;
}
return attrType.deepCopy( value, creationProcess.getCreationContext().getSessionFactory() );
}
@Override
public Serializable disassemble(Object value, SharedSessionContract session) {
throw new NotYetImplementedFor6Exception( getClass() );
}
@Override
public Object assemble(Serializable cached, SharedSessionContract session) {
throw new NotYetImplementedFor6Exception( getClass() );
}
};
@Override
public boolean isMutable() {
return true;
}
else {
mutabilityPlan = ImmutableMutabilityPlan.INSTANCE;
@Override
public Object deepCopy(Object value) {
if ( value == null ) {
return null;
}
return attrType.deepCopy( value, sessionFactory );
}
}
@Override
public PropertyAccess getPropertyAccess() {
return propertyAccess;
}
@Override
public Serializable disassemble(Object value, SharedSessionContract session) {
throw new NotYetImplementedFor6Exception( getClass() );
}
@Override
public MutabilityPlan getMutabilityPlan() {
return mutabilityPlan;
}
@Override
public boolean isNullable() {
return nullable;
}
@Override
public boolean isInsertable() {
return insertable;
}
@Override
public boolean isUpdatable() {
return updateable;
}
@Override
public boolean isIncludedInDirtyChecking() {
// todo (6.0) : do not believe this is correct
return updateable;
}
@Override
public boolean isIncludedInOptimisticLocking() {
return includeInOptimisticLocking;
}
@Override
public CascadeStyle getCascadeStyle() {
return cascadeStyle;
}
};
@Override
public Object assemble(Serializable cached, SharedSessionContract session) {
throw new NotYetImplementedFor6Exception( getClass() );
}
};
}
else {
mutabilityPlan = ImmutableMutabilityPlan.INSTANCE;
}
BasicAttributeMetadataAccess basicAttributeMetadataAccess = new BasicAttributeMetadataAccess( propertyAccess,
mutabilityPlan,
bootProperty.getValue().isNullable(),
bootProperty.isInsertable(),
bootProperty.isUpdateable(),
bootProperty.isOptimisticLocked(),
cascadeStyle );
return basicAttributeMetadataAccess;
}
@SuppressWarnings("rawtypes")
public static AttributeMetadataAccess getAttributeMetadataAccess(PropertyAccess propertyAccess) {
return new AttributeMetadataAccess() {
final AttributeMetadata attributeMetadata = new AttributeMetadata() {
private final MutabilityPlan mutabilityPlan = ImmutableMutabilityPlan.INSTANCE;
@Override
public PropertyAccess getPropertyAccess() {
return propertyAccess;
}
@Override
public MutabilityPlan getMutabilityPlan() {
return mutabilityPlan;
}
@Override
public boolean isNullable() {
return false;
}
@Override
public boolean isInsertable() {
return true;
}
@Override
public boolean isUpdatable() {
return false;
}
@Override
public boolean isIncludedInDirtyChecking() {
return false;
}
@Override
public boolean isIncludedInOptimisticLocking() {
// todo (6.0) : do not sure this is correct
return true;
}
@Override
public CascadeStyle getCascadeStyle() {
// todo (6.0) : do not sure this is correct
return null;
}
};
@Override
public AttributeMetadata resolveAttributeMetadata(EntityMappingType entityMappingType) {
return attributeMetadata;
}
};
return new BasicAttributeMetadataAccess(propertyAccess, ImmutableMutabilityPlan.INSTANCE, false, true, false, false, null);// todo (6.0) : not sure if CascadeStyle=null is correct
}
@SuppressWarnings("rawtypes")
@ -683,47 +542,14 @@ public class MappingModelCreationHelper {
}
}
final AttributeMetadata attributeMetadata = new AttributeMetadata() {
@Override
public PropertyAccess getPropertyAccess() {
return propertyAccess;
}
@Override
public MutabilityPlan getMutabilityPlan() {
return ImmutableMutabilityPlan.instance();
}
@Override
public boolean isNullable() {
return bootProperty.isOptional();
}
@Override
public boolean isInsertable() {
return bootProperty.isInsertable();
}
@Override
public boolean isUpdatable() {
return bootProperty.isUpdateable();
}
@Override
public boolean isIncludedInDirtyChecking() {
return false;
}
@Override
public boolean isIncludedInOptimisticLocking() {
return bootProperty.isOptimisticLocked();
}
@Override
public CascadeStyle getCascadeStyle() {
return cascadeStyle;
}
};
BasicAttributeMetadataAccess attributeMetadata = new BasicAttributeMetadataAccess( propertyAccess,
ImmutableMutabilityPlan.instance(),
bootProperty.isOptional(),
bootProperty.isInsertable(),
bootProperty.isUpdateable(),
bootProperty.isOptimisticLocked(),
cascadeStyle
);
final FetchStyle style = FetchOptionsHelper.determineFetchStyleByMetadata(
fetchMode,
@ -743,7 +569,7 @@ public class MappingModelCreationHelper {
attrName,
bootValueMapping,
propertyAccess,
entityMappingType -> attributeMetadata,
attributeMetadata,
collectionMappingType,
stateArrayPosition,
elementDescriptor,

View File

@ -78,6 +78,7 @@ import org.hibernate.engine.jdbc.mutation.spi.MutationExecutorService;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.CachedNaturalIdValueSource;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.CascadeStyles;
import org.hibernate.engine.spi.CollectionKey;
import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.EntityEntryFactory;
@ -174,6 +175,7 @@ import org.hibernate.metamodel.mapping.SelectableConsumer;
import org.hibernate.metamodel.mapping.SelectableMapping;
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
import org.hibernate.metamodel.mapping.VirtualModelPart;
import org.hibernate.metamodel.mapping.internal.BasicAttributeMetadataAccess;
import org.hibernate.metamodel.mapping.internal.BasicEntityIdentifierMappingImpl;
import org.hibernate.metamodel.mapping.internal.CompoundNaturalIdMapping;
import org.hibernate.metamodel.mapping.internal.DiscriminatedAssociationAttributeMapping;
@ -5499,55 +5501,22 @@ public abstract class AbstractEntityPersister
final AnyType anyType = (AnyType) attrType;
final MutabilityPlan<?> mutabilityPlan = new DiscriminatedAssociationAttributeMapping.MutabilityPlanImpl( anyType );
final BasicAttributeMetadataAccess attributeMetadataAccess = new BasicAttributeMetadataAccess(
propertyAccess,
mutabilityPlan,
bootProperty.isOptional(),
bootProperty.isInsertable(),
bootProperty.isUpdateable(),
bootProperty.isOptimisticLocked()
);
return new DiscriminatedAssociationAttributeMapping(
navigableRole.append( bootProperty.getName() ),
baseAssociationJtd,
this,
stateArrayPosition,
entityMappingType -> new AttributeMetadata() {
private final MutabilityPlan<?> mutabilityPlan = new DiscriminatedAssociationAttributeMapping.MutabilityPlanImpl( anyType );
private final boolean nullable = bootProperty.isOptional();
private final boolean insertable = bootProperty.isInsertable();
private final boolean updateable = bootProperty.isUpdateable();
private final boolean optimisticallyLocked = bootProperty.isOptimisticLocked();
@Override
public PropertyAccess getPropertyAccess() {
return propertyAccess;
}
@Override
public MutabilityPlan<?> getMutabilityPlan() {
return mutabilityPlan;
}
@Override
public boolean isNullable() {
return nullable;
}
@Override
public boolean isInsertable() {
return insertable;
}
@Override
public boolean isUpdatable() {
return updateable;
}
@Override
public boolean isIncludedInDirtyChecking() {
return updateable;
}
@Override
public boolean isIncludedInOptimisticLocking() {
return optimisticallyLocked;
}
},
attributeMetadataAccess,
bootProperty.isLazy() ? FetchTiming.DELAYED : FetchTiming.IMMEDIATE,
propertyAccess,
bootProperty,