From d2d40c73189a625e5058e2a146df35ef8fb1df01 Mon Sep 17 00:00:00 2001 From: Sanne Grinovero Date: Thu, 8 Dec 2022 13:51:09 +0000 Subject: [PATCH] HHH-15853 Avoid re-computing AttributeMetadataAccess at runtime --- .../mapping/AttributeMetadataAccess.java | 1 - .../internal/AbstractEmbeddableMapping.java | 52 +--- .../BasicAttributeMetadataAccess.java | 123 ++++++++ .../internal/EmbeddableMappingTypeImpl.java | 53 +--- .../internal/MappingModelCreationHelper.java | 270 ++++-------------- .../entity/AbstractEntityPersister.java | 57 +--- 6 files changed, 201 insertions(+), 355 deletions(-) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/BasicAttributeMetadataAccess.java diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/AttributeMetadataAccess.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/AttributeMetadataAccess.java index 965e6f302e..4e00167670 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/AttributeMetadataAccess.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/AttributeMetadataAccess.java @@ -12,7 +12,6 @@ package org.hibernate.metamodel.mapping; * * @author Steve Ebersole */ -@FunctionalInterface public interface AttributeMetadataAccess { /** * Resolve the details about the attribute diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/AbstractEmbeddableMapping.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/AbstractEmbeddableMapping.java index bdc8a8d325..4491c58e9e 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/AbstractEmbeddableMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/AbstractEmbeddableMapping.java @@ -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() ), diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/BasicAttributeMetadataAccess.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/BasicAttributeMetadataAccess.java new file mode 100644 index 0000000000..e6ff70dcad --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/BasicAttributeMetadataAccess.java @@ -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; + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EmbeddableMappingTypeImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EmbeddableMappingTypeImpl.java index 8094d6d444..32879974bb 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EmbeddableMappingTypeImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EmbeddableMappingTypeImpl.java @@ -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() ), 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 56a8a5f583..eb85e65250 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 @@ -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, diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java index 4704f2930f..c339a5f5b1 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java @@ -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,