HHH-18410 Make use of getter/setter cache as much as possible

This commit is contained in:
Christian Beikov 2024-07-23 15:15:06 +02:00
parent 420faa7e4a
commit b0a0ca15c6
28 changed files with 239 additions and 158 deletions

View File

@ -193,14 +193,14 @@ public abstract class AbstractEntityInsertAction extends EntityAction {
if ( attribute.isPluralAttributeMapping() ) { if ( attribute.isPluralAttributeMapping() ) {
addCollectionKey( addCollectionKey(
attribute.asPluralAttributeMapping(), attribute.asPluralAttributeMapping(),
attribute.getPropertyAccess().getGetter().get( object ), descriptor.getValue( object, i ),
persistenceContext persistenceContext
); );
} }
else if ( attribute.isEmbeddedAttributeMapping() ) { else if ( attribute.isEmbeddedAttributeMapping() ) {
visitEmbeddedAttributeMapping( visitEmbeddedAttributeMapping(
attribute.asEmbeddedAttributeMapping(), attribute.asEmbeddedAttributeMapping(),
attribute.getPropertyAccess().getGetter().get( object ), descriptor.getValue( object, i ),
persistenceContext persistenceContext
); );
} }

View File

@ -90,12 +90,18 @@ public final class Cascade {
LOG.tracev( "Processing cascade {0} for: {1}", action, persister.getEntityName() ); LOG.tracev( "Processing cascade {0} for: {1}", action, persister.getEntityName() );
} }
final PersistenceContext persistenceContext = eventSource.getPersistenceContextInternal(); final PersistenceContext persistenceContext = eventSource.getPersistenceContextInternal();
final EntityEntry entry = persistenceContext.getEntry( parent ); final boolean enhancedForLazyLoading = persister.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading();
if ( entry != null final EntityEntry entry;
&& entry.getLoadedState() == null if ( enhancedForLazyLoading ) {
&& entry.getStatus() == Status.MANAGED entry = persistenceContext.getEntry( parent );
&& persister.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading() ) { if ( entry != null
return; && entry.getLoadedState() == null
&& entry.getStatus() == Status.MANAGED ) {
return;
}
}
else {
entry = null;
} }
final Type[] types = persister.getPropertyTypes(); final Type[] types = persister.getPropertyTypes();
final String[] propertyNames = persister.getPropertyNames(); final String[] propertyNames = persister.getPropertyNames();
@ -113,6 +119,7 @@ public final class Cascade {
if ( style.doCascade( action ) ) { if ( style.doCascade( action ) ) {
final Object child; final Object child;
if ( isUninitializedProperty ) { if ( isUninitializedProperty ) {
assert enhancedForLazyLoading;
// parent is a bytecode enhanced entity. // parent is a bytecode enhanced entity.
// Cascade to an uninitialized, lazy value only if // Cascade to an uninitialized, lazy value only if
// parent is managed in the PersistenceContext. // parent is managed in the PersistenceContext.
@ -378,7 +385,7 @@ public final class Cascade {
* @return True if the attribute represents a logical one to one association * @return True if the attribute represents a logical one to one association
*/ */
private static boolean isLogicalOneToOne(Type type) { private static boolean isLogicalOneToOne(Type type) {
return type.isEntityType() && ( (EntityType) type ).isLogicalOneToOne(); return type instanceof EntityType && ( (EntityType) type ).isLogicalOneToOne();
} }
private static boolean cascadeAssociationNow( private static boolean cascadeAssociationNow(

View File

@ -145,8 +145,7 @@ public final class Collections {
Object entity, Object entity,
SessionImplementor session) { SessionImplementor session) {
collection.setOwner( entity ); collection.setOwner( entity );
final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); final CollectionEntry ce = session.getPersistenceContextInternal().getCollectionEntry( collection );
final CollectionEntry ce = persistenceContext.getCollectionEntry( collection );
if ( ce == null ) { if ( ce == null ) {
// refer to comment in StatefulPersistenceContext.addCollection() // refer to comment in StatefulPersistenceContext.addCollection()

View File

@ -414,7 +414,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
} }
@Override @Override
public EntityHolderImpl getEntityHolder(EntityKey key) { public @Nullable EntityHolderImpl getEntityHolder(EntityKey key) {
return entitiesByKey == null ? null : entitiesByKey.get( key ); return entitiesByKey == null ? null : entitiesByKey.get( key );
} }
@ -534,7 +534,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
} }
@Override @Override
public EntityHolderImpl removeEntityHolder(EntityKey key) { public @Nullable EntityHolderImpl removeEntityHolder(EntityKey key) {
final EntityHolderImpl holder; final EntityHolderImpl holder;
if ( entitiesByKey != null ) { if ( entitiesByKey != null ) {
holder = entitiesByKey.remove( key ); holder = entitiesByKey.remove( key );
@ -1333,8 +1333,8 @@ public class StatefulPersistenceContext implements PersistenceContext {
*/ */
@Override @Override
@Deprecated @Deprecated
public Map<PersistentCollection<?>,CollectionEntry> getCollectionEntries() { public @Nullable Map<PersistentCollection<?>,CollectionEntry> getCollectionEntries() {
return getOrInitializeCollectionEntries(); return collectionEntries;
} }
@Override @Override

View File

@ -524,11 +524,11 @@ public interface PersistenceContext {
@Incubating @Incubating
EntityHolder addEntityHolder(EntityKey key, Object entity); EntityHolder addEntityHolder(EntityKey key, Object entity);
EntityHolder getEntityHolder(EntityKey key); @Nullable EntityHolder getEntityHolder(EntityKey key);
boolean containsEntityHolder(EntityKey key); boolean containsEntityHolder(EntityKey key);
EntityHolder removeEntityHolder(EntityKey key); @Nullable EntityHolder removeEntityHolder(EntityKey key);
@Incubating @Incubating
void postLoad(JdbcValuesSourceProcessingState processingState, Consumer<EntityHolder> loadedConsumer); void postLoad(JdbcValuesSourceProcessingState processingState, Consumer<EntityHolder> loadedConsumer);
@ -567,7 +567,7 @@ public interface PersistenceContext {
* Doubly internal * Doubly internal
*/ */
@Internal @Internal
Map<PersistentCollection<?>,CollectionEntry> getCollectionEntries(); @Nullable Map<PersistentCollection<?>,CollectionEntry> getCollectionEntries();
/** /**
* Execute some action on each entry of the collectionEntries map, optionally iterating on a defensive copy. * Execute some action on each entry of the collectionEntries map, optionally iterating on a defensive copy.

View File

@ -14,6 +14,7 @@ import org.hibernate.action.internal.CollectionRecreateAction;
import org.hibernate.action.internal.CollectionRemoveAction; import org.hibernate.action.internal.CollectionRemoveAction;
import org.hibernate.action.internal.CollectionUpdateAction; import org.hibernate.action.internal.CollectionUpdateAction;
import org.hibernate.action.internal.QueuedOperationCollectionAction; import org.hibernate.action.internal.QueuedOperationCollectionAction;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.internal.Cascade; import org.hibernate.engine.internal.Cascade;
import org.hibernate.engine.internal.CascadePoint; import org.hibernate.engine.internal.CascadePoint;
import org.hibernate.engine.internal.Collections; import org.hibernate.engine.internal.Collections;
@ -21,6 +22,7 @@ import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
import org.hibernate.engine.spi.ActionQueue; import org.hibernate.engine.spi.ActionQueue;
import org.hibernate.engine.spi.CascadingAction; import org.hibernate.engine.spi.CascadingAction;
import org.hibernate.engine.spi.CascadingActions; import org.hibernate.engine.spi.CascadingActions;
import org.hibernate.engine.spi.CollectionEntry;
import org.hibernate.engine.spi.CollectionKey; import org.hibernate.engine.spi.CollectionKey;
import org.hibernate.engine.spi.EntityEntry; import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.PersistenceContext;
@ -35,6 +37,7 @@ import org.hibernate.event.spi.FlushEvent;
import org.hibernate.event.spi.PersistContext; import org.hibernate.event.spi.PersistContext;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.EntityPrinter; import org.hibernate.internal.util.EntityPrinter;
import org.hibernate.internal.util.collections.IdentityMap;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
@ -218,7 +221,12 @@ public abstract class AbstractFlushingEventListener implements JpaBootstrapSensi
// and reset reached, doupdate, etc. // and reset reached, doupdate, etc.
LOG.debug( "Dirty checking collections" ); LOG.debug( "Dirty checking collections" );
persistenceContext.forEachCollectionEntry( (pc,ce) -> ce.preFlush( pc ), true ); final Map<PersistentCollection<?>, CollectionEntry> collectionEntries = persistenceContext.getCollectionEntries();
if ( collectionEntries != null ) {
for ( Map.Entry<PersistentCollection<?>, CollectionEntry> entry : ( (IdentityMap<PersistentCollection<?>, CollectionEntry>) collectionEntries ).entryArray() ) {
entry.getValue().preFlush( entry.getKey() );
}
}
} }
/** /**
@ -297,14 +305,20 @@ public abstract class AbstractFlushingEventListener implements JpaBootstrapSensi
throws HibernateException { throws HibernateException {
LOG.trace( "Processing unreferenced collections" ); LOG.trace( "Processing unreferenced collections" );
final int count = persistenceContext.getCollectionEntriesSize(); final Map<PersistentCollection<?>, CollectionEntry> collectionEntries = persistenceContext.getCollectionEntries();
final int count;
persistenceContext.forEachCollectionEntry( if ( collectionEntries == null ) {
(persistentCollection, collectionEntry) -> { count = 0;
if ( !collectionEntry.isReached() && !collectionEntry.isIgnore() ) { }
Collections.processUnreachableCollection( persistentCollection, session ); else {
} count = collectionEntries.size();
}, true ); for ( Map.Entry<PersistentCollection<?>, CollectionEntry> me : ( (IdentityMap<PersistentCollection<?>, CollectionEntry>) collectionEntries ).entryArray() ) {
final CollectionEntry ce = me.getValue();
if ( !ce.isReached() && !ce.isIgnore() ) {
Collections.processUnreachableCollection( me.getKey(), session );
}
}
}
// Schedule updates to collections: // Schedule updates to collections:

View File

@ -353,8 +353,7 @@ public class DefaultMergeEventListener
.getMappingMetamodel() .getMappingMetamodel()
.getCollectionDescriptor( collectionType.getRole() ); .getCollectionDescriptor( collectionType.getRole() );
final CollectionEntry collectionEntry = getSession().getPersistenceContextInternal() final CollectionEntry collectionEntry = getSession().getPersistenceContextInternal()
.getCollectionEntries() .getCollectionEntry( coll );
.get( coll );
if ( !coll.equalsSnapshot( persister ) ) { if ( !coll.equalsSnapshot( persister ) ) {
collectionEntry.resetStoredSnapshot( coll, coll.getSnapshot( persister ) ); collectionEntry.resetStoredSnapshot( coll, coll.getSnapshot( persister ) );
} }

View File

@ -24,7 +24,7 @@ public final class IdentityMap<K,V> implements Map<K,V> {
private final LinkedHashMap<IdentityKey<K>,V> map; private final LinkedHashMap<IdentityKey<K>,V> map;
private transient Entry<IdentityKey<K>,V>[] entryArray = null; private transient Entry<K,V>[] entryArray = null;
/** /**
* Return a new instance of this class, with iteration * Return a new instance of this class, with iteration
@ -151,15 +151,14 @@ public final class IdentityMap<K,V> implements Map<K,V> {
return set; return set;
} }
@SuppressWarnings( {"unchecked"}) public Entry<K,V>[] entryArray() {
public Entry[] entryArray() {
if ( entryArray == null ) { if ( entryArray == null ) {
entryArray = new Entry[ map.size() ]; entryArray = new Entry[ map.size() ];
final Iterator<Entry<IdentityKey<K>, V>> itr = map.entrySet().iterator(); final Iterator<Entry<IdentityKey<K>, V>> itr = map.entrySet().iterator();
int i = 0; int i = 0;
while ( itr.hasNext() ) { while ( itr.hasNext() ) {
final Entry<IdentityKey<K>, V> me = itr.next(); final Entry<IdentityKey<K>, V> me = itr.next();
entryArray[i++] = new IdentityMapEntry( me.getKey().key, me.getValue() ); entryArray[i++] = new IdentityMapEntry<>( me.getKey().key, me.getValue() );
} }
} }
return entryArray; return entryArray;

View File

@ -195,7 +195,7 @@ public abstract class AbstractCompositeIdentifierMapping
else { else {
for ( int i = 0; i < size; i++ ) { for ( int i = 0; i < size; i++ ) {
final AttributeMapping attributeMapping = embeddableTypeDescriptor.getAttributeMapping( i ); final AttributeMapping attributeMapping = embeddableTypeDescriptor.getAttributeMapping( i );
final Object o = attributeMapping.getPropertyAccess().getGetter().get( value ); final Object o = embeddableTypeDescriptor.getValue( value, i );
if ( attributeMapping instanceof ToOneAttributeMapping ) { if ( attributeMapping instanceof ToOneAttributeMapping ) {
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attributeMapping; final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attributeMapping;
final ForeignKeyDescriptor fkDescriptor = toOneAttributeMapping.getForeignKeyDescriptor(); final ForeignKeyDescriptor fkDescriptor = toOneAttributeMapping.getForeignKeyDescriptor();

View File

@ -56,14 +56,14 @@ public interface AttributeMapping
* Convenient access to getting the value for this attribute from the declarer * Convenient access to getting the value for this attribute from the declarer
*/ */
default Object getValue(Object container) { default Object getValue(Object container) {
return getPropertyAccess().getGetter().get( container ); return getDeclaringType().getValue( container, getStateArrayPosition() );
} }
/** /**
* Convenient access to setting the value for this attribute on the declarer * Convenient access to setting the value for this attribute on the declarer
*/ */
default void setValue(Object container, Object value) { default void setValue(Object container, Object value) {
getPropertyAccess().getSetter().set( container, value ); getDeclaringType().setValue( container, getStateArrayPosition(), value );
} }
/** /**

View File

@ -361,9 +361,8 @@ public interface EmbeddableMappingType extends ManagedMappingType, SelectableMap
default int compare(Object value1, Object value2) { default int compare(Object value1, Object value2) {
final AttributeMappingsList attributeMappings = getAttributeMappings(); final AttributeMappingsList attributeMappings = getAttributeMappings();
for ( int i = 0; i < attributeMappings.size(); i++ ) { for ( int i = 0; i < attributeMappings.size(); i++ ) {
AttributeMapping attributeMapping = attributeMappings.get( i ); final AttributeMapping attribute = attributeMappings.get( i );
final Getter getter = attributeMapping.getPropertyAccess().getGetter(); final int comparison = attribute.compare( attribute.getValue( value1 ), attribute.getValue( value2 ) );
final int comparison = attributeMapping.compare( getter.get( value1 ), getter.get( value2 ) );
if ( comparison != 0 ) { if ( comparison != 0 ) {
return comparison; return comparison;
} }

View File

@ -80,7 +80,7 @@ public interface ManagedMappingType extends MappingType, FetchableContainer {
* Extract a specific attribute value from the entity instance, by position * Extract a specific attribute value from the entity instance, by position
*/ */
default Object getValue(Object instance, int position) { default Object getValue(Object instance, int position) {
return getAttributeMapping( position ).getValue( instance ); return getAttributeMapping( position ).getPropertyAccess().getGetter().get( instance );
} }
/** /**
@ -92,7 +92,7 @@ public interface ManagedMappingType extends MappingType, FetchableContainer {
* Inject a specific attribute value into the entity instance, by position * Inject a specific attribute value into the entity instance, by position
*/ */
default void setValue(Object instance, int position, Object value) { default void setValue(Object instance, int position, Object value) {
getAttributeMapping( position ).setValue( instance, value ); getAttributeMapping( position ).getPropertyAccess().getSetter().set( instance, value );
} }
default boolean anyRequiresAggregateColumnWriter() { default boolean anyRequiresAggregateColumnWriter() {

View File

@ -55,6 +55,7 @@ import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.property.access.internal.PropertyAccessStrategyBackRefImpl; import org.hibernate.property.access.internal.PropertyAccessStrategyBackRefImpl;
import org.hibernate.property.access.spi.Getter; import org.hibernate.property.access.spi.Getter;
import org.hibernate.property.access.spi.PropertyAccess; import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.property.access.spi.Setter;
import org.hibernate.sql.ast.tree.from.TableGroupProducer; import org.hibernate.sql.ast.tree.from.TableGroupProducer;
import org.hibernate.sql.results.graph.Fetchable; import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.type.AnyType; import org.hibernate.type.AnyType;
@ -75,6 +76,8 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType
EmbeddableMappingType.ConcreteEmbeddableType { EmbeddableMappingType.ConcreteEmbeddableType {
final protected MutableAttributeMappingList attributeMappings; final protected MutableAttributeMappingList attributeMappings;
protected SelectableMappings selectableMappings; protected SelectableMappings selectableMappings;
protected Getter[] getterCache;
protected Setter[] setterCache;
public AbstractEmbeddableMapping(MutableAttributeMappingList attributeMappings) { public AbstractEmbeddableMapping(MutableAttributeMappingList attributeMappings) {
this.attributeMappings = attributeMappings; this.attributeMappings = attributeMappings;
@ -100,6 +103,16 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType
return true; return true;
} }
@Override
public Object getValue(Object instance, int position) {
return getterCache[position].get( instance );
}
@Override
public void setValue(Object instance, int position, Object value) {
setterCache[position].set( instance, value );
}
@Override @Override
public Object getDiscriminatorValue() { public Object getDiscriminatorValue() {
return null; return null;
@ -127,10 +140,7 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType
protected Object[] getAttributeValues(Object compositeInstance) { protected Object[] getAttributeValues(Object compositeInstance) {
final Object[] results = new Object[getNumberOfAttributeMappings()]; final Object[] results = new Object[getNumberOfAttributeMappings()];
for ( int i = 0; i < results.length; i++ ) { for ( int i = 0; i < results.length; i++ ) {
final Getter getter = getAttributeMapping( i ).getAttributeMetadata() results[i] = getValue( compositeInstance, i );
.getPropertyAccess()
.getGetter();
results[i] = getter.get( compositeInstance );
} }
return results; return results;
} }
@ -148,7 +158,7 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType
protected void setAttributeValues(Object component, Object[] values) { protected void setAttributeValues(Object component, Object[] values) {
for ( int i = 0; i < values.length; i++ ) { for ( int i = 0; i < values.length; i++ ) {
getAttributeMapping( i ).getPropertyAccess().getSetter().set( component, values[i] ); setValue( component, i, values[i] );
} }
} }
@ -253,6 +263,7 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType
} }
mappings.add( attributeMapping ); mappings.add( attributeMapping );
} }
buildGetterSetterCache();
return true; return true;
} }
@ -737,7 +748,7 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType
if ( attributeMapping instanceof PluralAttributeMapping ) { if ( attributeMapping instanceof PluralAttributeMapping ) {
continue; continue;
} }
final Object o = attributeMapping.getPropertyAccess().getGetter().get( value ); final Object o = getValue( value, i );
span += attributeMapping.forEachJdbcValue( o, span + offset, x, y, valuesConsumer, session ); span += attributeMapping.forEachJdbcValue( o, span + offset, x, y, valuesConsumer, session );
} }
} }
@ -777,10 +788,24 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType
} }
this.selectableMappings = new SelectableMappingsImpl( selectableMappings.toArray( new SelectableMapping[0] ) ); this.selectableMappings = new SelectableMappingsImpl( selectableMappings.toArray( new SelectableMapping[0] ) );
buildGetterSetterCache();
return true; return true;
} }
protected void buildGetterSetterCache() {
final int propertySpan = attributeMappings.size();
final Getter[] getterCache = new Getter[propertySpan];
final Setter[] setterCache = new Setter[propertySpan];
for ( int i = 0; i < propertySpan; i++ ) {
final PropertyAccess propertyAccess = attributeMappings.get( i ).getPropertyAccess();
getterCache[i] = propertyAccess.getGetter();
setterCache[i] = propertyAccess.getSetter();
}
this.getterCache = getterCache;
this.setterCache = setterCache;
}
private static MutabilityPlan<?> getMutabilityPlan(boolean updateable) { private static MutabilityPlan<?> getMutabilityPlan(boolean updateable) {
if ( updateable ) { if ( updateable ) {
return new MutabilityPlan<>() { return new MutabilityPlan<>() {

View File

@ -49,6 +49,7 @@ import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.metamodel.mapping.SelectableConsumer; import org.hibernate.metamodel.mapping.SelectableConsumer;
import org.hibernate.metamodel.mapping.SelectableMapping; import org.hibernate.metamodel.mapping.SelectableMapping;
import org.hibernate.metamodel.mapping.SelectableMappings; import org.hibernate.metamodel.mapping.SelectableMappings;
@ -862,6 +863,7 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme
return concreteEmbeddableByDiscriminator == null ? this : concreteEmbeddableByDiscriminator.get( discriminatorValue ); return concreteEmbeddableByDiscriminator == null ? this : concreteEmbeddableByDiscriminator.get( discriminatorValue );
} }
@Override
public ConcreteEmbeddableType findSubtypeBySubclass(String subclassName) { public ConcreteEmbeddableType findSubtypeBySubclass(String subclassName) {
return concreteEmbeddableBySubclass == null ? this : concreteEmbeddableBySubclass.get( subclassName ); return concreteEmbeddableBySubclass == null ? this : concreteEmbeddableBySubclass.get( subclassName );
} }
@ -872,16 +874,6 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme
return (Collection<ConcreteEmbeddableType>) (Collection<?>) concreteEmbeddableBySubclass.values(); return (Collection<ConcreteEmbeddableType>) (Collection<?>) concreteEmbeddableBySubclass.values();
} }
@Override
public Object getValue(Object instance, int position) {
final AttributeMapping attributeMapping = getAttributeMapping( position );
final ConcreteEmbeddableType concreteEmbeddableType = findSubtypeBySubclass( instance.getClass().getName() );
if ( concreteEmbeddableType.declaresAttribute( attributeMapping ) ) {
return attributeMapping.getValue( instance );
}
return null;
}
@Override @Override
protected Object[] getAttributeValues(Object compositeInstance) { protected Object[] getAttributeValues(Object compositeInstance) {
if ( !isPolymorphic() ) { if ( !isPolymorphic() ) {
@ -893,16 +885,9 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme
final ConcreteEmbeddableType concreteEmbeddableType = findSubtypeBySubclass( compositeInstance.getClass().getName() ); final ConcreteEmbeddableType concreteEmbeddableType = findSubtypeBySubclass( compositeInstance.getClass().getName() );
int i = 0; int i = 0;
for ( ; i < numberOfAttributes; i++ ) { for ( ; i < numberOfAttributes; i++ ) {
final AttributeMapping attributeMapping = getAttributeMapping( i ); results[i] = concreteEmbeddableType.declaresAttribute( i )
if ( concreteEmbeddableType.declaresAttribute( attributeMapping ) ) { ? getValue( compositeInstance, i )
final Getter getter = attributeMapping.getAttributeMetadata() : null;
.getPropertyAccess()
.getGetter();
results[i] = getter.get( compositeInstance );
}
else {
results[i] = null;
}
} }
results[i] = compositeInstance.getClass().getName(); results[i] = compositeInstance.getClass().getName();
return results; return results;
@ -920,7 +905,7 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme
for ( int i = 0; i < getNumberOfAttributeMappings(); i++ ) { for ( int i = 0; i < getNumberOfAttributeMappings(); i++ ) {
final AttributeMapping attributeMapping = getAttributeMapping( i ); final AttributeMapping attributeMapping = getAttributeMapping( i );
if ( concreteEmbeddableType.declaresAttribute( attributeMapping ) ) { if ( concreteEmbeddableType.declaresAttribute( attributeMapping ) ) {
attributeMapping.getPropertyAccess().getSetter().set( component, values[i] ); setValue( component, i, values[i] );
} }
else if ( values[i] != null ) { else if ( values[i] != null ) {
throw new IllegalArgumentException( String.format( throw new IllegalArgumentException( String.format(
@ -982,7 +967,7 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme
if ( !attributeMapping.isPluralAttributeMapping() ) { if ( !attributeMapping.isPluralAttributeMapping() ) {
final Object attributeValue = concreteEmbeddableType == null || !concreteEmbeddableType.declaresAttribute( attributeMapping ) final Object attributeValue = concreteEmbeddableType == null || !concreteEmbeddableType.declaresAttribute( attributeMapping )
? null ? null
: attributeMapping.getPropertyAccess().getGetter().get( domainValue ); : getValue( domainValue, i );
span += attributeMapping.breakDownJdbcValues( span += attributeMapping.breakDownJdbcValues(
attributeValue, attributeValue,
offset + span, offset + span,
@ -1001,6 +986,47 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme
return span; return span;
} }
@Override
public <X, Y> int forEachJdbcValue(
Object value,
int offset,
X x,
Y y,
JdbcValuesBiConsumer<X, Y> valuesConsumer,
SharedSessionContractImplementor session) {
int span = 0;
if ( value == null ) {
for ( int i = 0; i < attributeMappings.size(); i++ ) {
final AttributeMapping attributeMapping = attributeMappings.get( i );
if ( attributeMapping instanceof PluralAttributeMapping ) {
continue;
}
span += attributeMapping.forEachJdbcValue( null, span + offset, x, y, valuesConsumer, session );
}
if ( isPolymorphic() ) {
span += discriminatorMapping.forEachJdbcValue( null, offset + span, x, y, valuesConsumer, session );
}
}
else {
final ConcreteEmbeddableType concreteEmbeddableType = findSubtypeBySubclass( value.getClass().getName() );
for ( int i = 0; i < attributeMappings.size(); i++ ) {
final AttributeMapping attributeMapping = attributeMappings.get( i );
if ( attributeMapping instanceof PluralAttributeMapping ) {
continue;
}
final Object attributeValue = concreteEmbeddableType == null || !concreteEmbeddableType.declaresAttribute( attributeMapping )
? null
: getValue( value, i );
span += attributeMapping.forEachJdbcValue( attributeValue, span + offset, x, y, valuesConsumer, session );
}
if ( isPolymorphic() ) {
final Object d = concreteEmbeddableType == null ? null : concreteEmbeddableType.getDiscriminatorValue();
span += discriminatorMapping.forEachJdbcValue( d, offset + span, x, y, valuesConsumer, session );
}
}
return span;
}
@Override @Override
public <X, Y> int decompose( public <X, Y> int decompose(
Object domainValue, Object domainValue,

View File

@ -143,7 +143,9 @@ public class EmbeddedAttributeMapping
MappingModelCreationProcess creationProcess) { MappingModelCreationProcess creationProcess) {
super( super(
inverseModelPart.getFetchableName(), inverseModelPart.getFetchableName(),
-1, inverseModelPart.asAttributeMapping() != null
? inverseModelPart.asAttributeMapping().getStateArrayPosition()
: -1,
inverseModelPart.getFetchableKey(), inverseModelPart.getFetchableKey(),
inverseModelPart.asAttributeMapping() != null inverseModelPart.asAttributeMapping() != null
? inverseModelPart.asAttributeMapping().getAttributeMetadata() ? inverseModelPart.asAttributeMapping().getAttributeMetadata()

View File

@ -165,7 +165,7 @@ public class IdClassEmbeddable extends AbstractEmbeddableMapping implements Iden
for ( int i = 0; i < propertyValues.length; i++ ) { for ( int i = 0; i < propertyValues.length; i++ ) {
final AttributeMapping attributeMapping = virtualIdEmbeddable.getAttributeMapping( i ); final AttributeMapping attributeMapping = virtualIdEmbeddable.getAttributeMapping( i );
final Object o = attributeMapping.getPropertyAccess().getGetter().get( entity ); final Object o = attributeMapping.getValue( entity );
if ( o == null ) { if ( o == null ) {
final AttributeMapping idClassAttributeMapping = getAttributeMapping( i ); final AttributeMapping idClassAttributeMapping = getAttributeMapping( i );
if ( idClassAttributeMapping.getPropertyAccess().getGetter().getReturnTypeClass().isPrimitive() ) { if ( idClassAttributeMapping.getPropertyAccess().getGetter().getReturnTypeClass().isPrimitive() ) {
@ -210,7 +210,7 @@ public class IdClassEmbeddable extends AbstractEmbeddableMapping implements Iden
virtualIdEmbeddable.forEachAttribute( virtualIdEmbeddable.forEachAttribute(
(position, virtualIdAttribute) -> { (position, virtualIdAttribute) -> {
final AttributeMapping idClassAttribute = attributeMappings.get( position ); final AttributeMapping idClassAttribute = attributeMappings.get( position );
Object o = idClassAttribute.getPropertyAccess().getGetter().get( id ); Object o = idClassAttribute.getValue( id );
if ( virtualIdAttribute instanceof ToOneAttributeMapping && !( idClassAttribute instanceof ToOneAttributeMapping ) ) { if ( virtualIdAttribute instanceof ToOneAttributeMapping && !( idClassAttribute instanceof ToOneAttributeMapping ) ) {
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) virtualIdAttribute; final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) virtualIdAttribute;
final EntityPersister entityPersister = toOneAttributeMapping.getEntityMappingType() final EntityPersister entityPersister = toOneAttributeMapping.getEntityMappingType()

View File

@ -205,7 +205,7 @@ public class InverseNonAggregatedIdentifierMapping extends EmbeddedAttributeMapp
final Object[] propertyValues = new Object[embeddableTypeDescriptor.getNumberOfAttributeMappings()]; final Object[] propertyValues = new Object[embeddableTypeDescriptor.getNumberOfAttributeMappings()];
for ( int i = 0; i < propertyValues.length; i++ ) { for ( int i = 0; i < propertyValues.length; i++ ) {
final AttributeMapping attributeMapping = embeddableTypeDescriptor.getAttributeMapping( i ); final AttributeMapping attributeMapping = embeddableTypeDescriptor.getAttributeMapping( i );
final Object o = attributeMapping.getPropertyAccess().getGetter().get( entity ); final Object o = attributeMapping.getValue( entity );
if ( o == null ) { if ( o == null ) {
final AttributeMapping idClassAttributeMapping = identifierValueMapper.getAttributeMapping( i ); final AttributeMapping idClassAttributeMapping = identifierValueMapper.getAttributeMapping( i );
if ( idClassAttributeMapping.getPropertyAccess().getGetter().getReturnTypeClass().isPrimitive() ) { if ( idClassAttributeMapping.getPropertyAccess().getGetter().getReturnTypeClass().isPrimitive() ) {
@ -249,7 +249,7 @@ public class InverseNonAggregatedIdentifierMapping extends EmbeddedAttributeMapp
for ( int position = 0; position < propertyValues.length; position++ ) { for ( int position = 0; position < propertyValues.length; position++ ) {
final AttributeMapping attribute = embeddableTypeDescriptor.getAttributeMapping( position ); final AttributeMapping attribute = embeddableTypeDescriptor.getAttributeMapping( position );
final AttributeMapping mappedIdAttributeMapping = identifierValueMapper.getAttributeMapping( position ); final AttributeMapping mappedIdAttributeMapping = identifierValueMapper.getAttributeMapping( position );
Object o = mappedIdAttributeMapping.getPropertyAccess().getGetter().get( id ); Object o = mappedIdAttributeMapping.getValue( id );
if ( attribute instanceof ToOneAttributeMapping && !( mappedIdAttributeMapping instanceof ToOneAttributeMapping ) ) { if ( attribute instanceof ToOneAttributeMapping && !( mappedIdAttributeMapping instanceof ToOneAttributeMapping ) ) {
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attribute; final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attribute;
final EntityPersister entityPersister = toOneAttributeMapping.getEntityMappingType() final EntityPersister entityPersister = toOneAttributeMapping.getEntityMappingType()
@ -260,11 +260,8 @@ public class InverseNonAggregatedIdentifierMapping extends EmbeddedAttributeMapp
// use the managed object i.e. proxy or initialized entity // use the managed object i.e. proxy or initialized entity
o = holder == null ? null : holder.getManagedObject(); o = holder == null ? null : holder.getManagedObject();
if ( o == null ) { if ( o == null ) {
o = entityDescriptor o = entityDescriptor.findAttributeMapping( toOneAttributeMapping.getAttributeName() )
.findAttributeMapping( toOneAttributeMapping.getAttributeName() ) .getValue( entity );
.getPropertyAccess()
.getGetter()
.get( entity );
} }
} }
propertyValues[position] = o; propertyValues[position] = o;

View File

@ -246,7 +246,7 @@ public class NonAggregatedIdentifierMappingImpl extends AbstractCompositeIdentif
final Object[] propertyValues = new Object[embeddableTypeDescriptor.getNumberOfAttributeMappings()]; final Object[] propertyValues = new Object[embeddableTypeDescriptor.getNumberOfAttributeMappings()];
for ( int i = 0; i < propertyValues.length; i++ ) { for ( int i = 0; i < propertyValues.length; i++ ) {
final AttributeMapping attributeMapping = embeddableTypeDescriptor.getAttributeMapping( i ); final AttributeMapping attributeMapping = embeddableTypeDescriptor.getAttributeMapping( i );
final Object o = attributeMapping.getPropertyAccess().getGetter().get( entity ); final Object o = attributeMapping.getValue( entity );
if ( o == null ) { if ( o == null ) {
final AttributeMapping idClassAttributeMapping = identifierValueMapper.getAttributeMapping( i ); final AttributeMapping idClassAttributeMapping = identifierValueMapper.getAttributeMapping( i );
if ( idClassAttributeMapping.getPropertyAccess().getGetter().getReturnTypeClass().isPrimitive() ) { if ( idClassAttributeMapping.getPropertyAccess().getGetter().getReturnTypeClass().isPrimitive() ) {
@ -292,7 +292,7 @@ public class NonAggregatedIdentifierMappingImpl extends AbstractCompositeIdentif
for ( int i = 0; i < propertyValues.length; i++ ) { for ( int i = 0; i < propertyValues.length; i++ ) {
final AttributeMapping attribute = embeddableTypeDescriptor.getAttributeMapping( i ); final AttributeMapping attribute = embeddableTypeDescriptor.getAttributeMapping( i );
final AttributeMapping mappedIdAttributeMapping = identifierValueMapper.getAttributeMapping( i ); final AttributeMapping mappedIdAttributeMapping = identifierValueMapper.getAttributeMapping( i );
Object o = mappedIdAttributeMapping.getPropertyAccess().getGetter().get( id ); Object o = mappedIdAttributeMapping.getValue( id );
if ( attribute instanceof ToOneAttributeMapping && !( mappedIdAttributeMapping instanceof ToOneAttributeMapping ) ) { if ( attribute instanceof ToOneAttributeMapping && !( mappedIdAttributeMapping instanceof ToOneAttributeMapping ) ) {
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attribute; final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attribute;
final EntityPersister entityPersister = toOneAttributeMapping.getEntityMappingType().getEntityPersister(); final EntityPersister entityPersister = toOneAttributeMapping.getEntityMappingType().getEntityPersister();

View File

@ -258,9 +258,8 @@ public class VirtualIdEmbeddable extends AbstractEmbeddableMapping implements Id
else { else {
final AttributeMappingsList attributeMappings = getAttributeMappings(); final AttributeMappingsList attributeMappings = getAttributeMappings();
for ( int i = 0; i < attributeMappings.size(); i++ ) { for ( int i = 0; i < attributeMappings.size(); i++ ) {
final AttributeMapping attributeMapping = attributeMappings.get( i ); final AttributeMapping attribute = attributeMappings.get( i );
final Getter getter = attributeMapping.getPropertyAccess().getGetter(); if ( !attribute.areEqual( attribute.getValue( one ), attribute.getValue( other ), session ) ) {
if ( !attributeMapping.areEqual( getter.get( one ), getter.get( other ), session ) ) {
return false; return false;
} }
} }
@ -274,9 +273,8 @@ public class VirtualIdEmbeddable extends AbstractEmbeddableMapping implements Id
if ( idClassEmbeddable != null ) { if ( idClassEmbeddable != null ) {
final AttributeMappingsList attributeMappings = idClassEmbeddable.getAttributeMappings(); final AttributeMappingsList attributeMappings = idClassEmbeddable.getAttributeMappings();
for ( int i = 0; i < attributeMappings.size(); i++ ) { for ( int i = 0; i < attributeMappings.size(); i++ ) {
final AttributeMapping attributeMapping = attributeMappings.get( i ); final AttributeMapping attribute = attributeMappings.get( i );
final Getter getter = attributeMapping.getPropertyAccess().getGetter(); final int comparison = attribute.compare( attribute.getValue( value1 ), attribute.getValue( value2 ) );
final int comparison = attributeMapping.compare( getter.get( value1 ), getter.get( value2 ) );
if ( comparison != 0 ) { if ( comparison != 0 ) {
return comparison; return comparison;
} }

View File

@ -225,6 +225,7 @@ import org.hibernate.persister.entity.mutation.UpdateCoordinatorNoOp;
import org.hibernate.persister.entity.mutation.UpdateCoordinatorStandard; import org.hibernate.persister.entity.mutation.UpdateCoordinatorStandard;
import org.hibernate.persister.internal.SqlFragmentPredicate; import org.hibernate.persister.internal.SqlFragmentPredicate;
import org.hibernate.persister.spi.PersisterCreationContext; import org.hibernate.persister.spi.PersisterCreationContext;
import org.hibernate.property.access.spi.Getter;
import org.hibernate.property.access.spi.PropertyAccess; import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.property.access.spi.Setter; import org.hibernate.property.access.spi.Setter;
import org.hibernate.query.PathException; import org.hibernate.query.PathException;
@ -465,6 +466,9 @@ public abstract class AbstractEntityPersister
private AttributeMappingsList attributeMappings; private AttributeMappingsList attributeMappings;
protected AttributeMappingsMap declaredAttributeMappings = AttributeMappingsMap.builder().build(); protected AttributeMappingsMap declaredAttributeMappings = AttributeMappingsMap.builder().build();
protected AttributeMappingsList staticFetchableList; protected AttributeMappingsList staticFetchableList;
// We build a cache for getters and setters to avoid megamorphic calls
private Getter[] getterCache;
private Setter[] setterCache;
private final String queryLoaderName; private final String queryLoaderName;
@ -4491,23 +4495,19 @@ public abstract class AbstractEntityPersister
accessOptimizer.setPropertyValues( object, values ); accessOptimizer.setPropertyValues( object, values );
} }
else { else {
if ( hasSubclasses() ) { final BytecodeEnhancementMetadata enhancementMetadata = entityMetamodel.getBytecodeEnhancementMetadata();
final AttributeMappingsList attributeMappings = getAttributeMappings();
if ( enhancementMetadata.isEnhancedForLazyLoading() ) {
for ( int i = 0; i < attributeMappings.size(); i++ ) { for ( int i = 0; i < attributeMappings.size(); i++ ) {
final Object value = values[i]; final Object value = values[i];
if ( value != UNFETCHED_PROPERTY ) { if ( value != UNFETCHED_PROPERTY ) {
final Setter setter = attributeMappings.get( i ).getPropertyAccess().getSetter(); setterCache[i].set( object, value );
setter.set( object, value );
} }
} }
} }
else { else {
for ( int i = 0; i < staticFetchableList.size(); i++ ) { for ( int i = 0; i < attributeMappings.size(); i++ ) {
final AttributeMapping attribute = staticFetchableList.get( i ); setterCache[i].set( object, values[i] );
final Object value = values[i];
if ( value != UNFETCHED_PROPERTY ) {
final Setter setter = attribute.getPropertyAccess().getSetter();
setter.set( object, value );
}
} }
} }
} }
@ -4515,8 +4515,7 @@ public abstract class AbstractEntityPersister
@Override @Override
public void setPropertyValue(Object object, int i, Object value) { public void setPropertyValue(Object object, int i, Object value) {
final String propertyName = getPropertyNames()[i]; setterCache[i].set( object, value );
setPropertyValue( object, propertyName, value );
} }
@Override @Override
@ -4526,17 +4525,24 @@ public abstract class AbstractEntityPersister
} }
else { else {
final BytecodeEnhancementMetadata enhancementMetadata = entityMetamodel.getBytecodeEnhancementMetadata(); final BytecodeEnhancementMetadata enhancementMetadata = entityMetamodel.getBytecodeEnhancementMetadata();
final LazyAttributesMetadata lazyAttributesMetadata = enhancementMetadata.getLazyAttributesMetadata(); final AttributeMappingsList attributeMappings = getAttributeMappings();
final Object[] values = new Object[ getNumberOfAttributeMappings() ]; final Object[] values = new Object[attributeMappings.size()];
for ( int i = 0; i < attributeMappings.size(); i++ ) { if ( enhancementMetadata.isEnhancedForLazyLoading() ) {
final AttributeMapping attributeMapping = attributeMappings.get( i ); final LazyAttributesMetadata lazyAttributesMetadata = enhancementMetadata.getLazyAttributesMetadata();
final AttributeMetadata attributeMetadata = attributeMapping.getAttributeMetadata(); for ( int i = 0; i < attributeMappings.size(); i++ ) {
if ( ! lazyAttributesMetadata.isLazyAttribute( attributeMapping.getAttributeName() ) final AttributeMapping attributeMapping = attributeMappings.get( i );
|| enhancementMetadata.isAttributeLoaded( object, attributeMapping.getAttributeName() ) ) { if ( !lazyAttributesMetadata.isLazyAttribute( attributeMapping.getAttributeName() )
values[i] = attributeMetadata.getPropertyAccess().getGetter().get( object ); || enhancementMetadata.isAttributeLoaded( object, attributeMapping.getAttributeName() ) ) {
values[i] = getterCache[i].get( object );
}
else {
values[i] = LazyPropertyInitializer.UNFETCHED_PROPERTY;
}
} }
else { }
values[i] = LazyPropertyInitializer.UNFETCHED_PROPERTY; else {
for ( int i = 0; i < attributeMappings.size(); i++ ) {
values[i] = getterCache[i].get( object );
} }
} }
@ -4546,7 +4552,7 @@ public abstract class AbstractEntityPersister
@Override @Override
public Object getPropertyValue(Object object, int i) { public Object getPropertyValue(Object object, int i) {
return attributeMappings.get( i ).getAttributeMetadata().getPropertyAccess().getGetter().get( object ); return getterCache[i].get( object );
} }
@Override @Override
@ -4559,7 +4565,7 @@ public abstract class AbstractEntityPersister
ManagedMappingType baseValueType = null; ManagedMappingType baseValueType = null;
Object baseValue = null; Object baseValue = null;
if ( attributeMapping != null ) { if ( attributeMapping != null ) {
baseValue = attributeMapping.getAttributeMetadata().getPropertyAccess().getGetter().get( object ); baseValue = getterCache[attributeMapping.getStateArrayPosition()].get( object );
if ( dotIndex != -1 ) { if ( dotIndex != -1 ) {
baseValueType = (ManagedMappingType) attributeMapping.getMappedType(); baseValueType = (ManagedMappingType) attributeMapping.getMappedType();
} }
@ -4570,7 +4576,7 @@ public abstract class AbstractEntityPersister
null null
).asAttributeMapping(); ).asAttributeMapping();
if ( mapping != null ) { if ( mapping != null ) {
baseValue = mapping.getAttributeMetadata().getPropertyAccess().getGetter().get( object ); baseValue = mapping.getValue( object );
if ( dotIndex != -1 ) { if ( dotIndex != -1 ) {
baseValueType = (ManagedMappingType) mapping.getMappedType(); baseValueType = (ManagedMappingType) mapping.getMappedType();
} }
@ -4592,7 +4598,7 @@ public abstract class AbstractEntityPersister
final int endIndex = nextDotIndex == -1 ? propertyName.length() : nextDotIndex; final int endIndex = nextDotIndex == -1 ? propertyName.length() : nextDotIndex;
final AttributeMapping attributeMapping = final AttributeMapping attributeMapping =
baseValueType.findAttributeMapping( propertyName.substring( dotIndex + 1, endIndex ) ); baseValueType.findAttributeMapping( propertyName.substring( dotIndex + 1, endIndex ) );
baseValue = attributeMapping.getAttributeMetadata().getPropertyAccess().getGetter().get( baseValue ); baseValue = attributeMapping.getValue( baseValue );
baseValueType = nextDotIndex == -1 ? null : (ManagedMappingType) attributeMapping.getMappedType(); baseValueType = nextDotIndex == -1 ? null : (ManagedMappingType) attributeMapping.getMappedType();
return getPropertyValue( baseValue, baseValueType, propertyName, nextDotIndex ); return getPropertyValue( baseValue, baseValueType, propertyName, nextDotIndex );
} }
@ -4712,9 +4718,7 @@ public abstract class AbstractEntityPersister
final Object[] result = new Object[attributeMappings.size()]; final Object[] result = new Object[attributeMappings.size()];
for ( int i = 0; i < attributeMappings.size(); i++ ) { for ( int i = 0; i < attributeMappings.size(); i++ ) {
result[i] = attributeMappings.get( i ) result[i] = getterCache[i].getForInsert( entity, mergeMap, session );
.getPropertyAccess().getGetter()
.getForInsert( entity, mergeMap, session );
} }
return result; return result;
} }
@ -4888,8 +4892,7 @@ public abstract class AbstractEntityPersister
@Override @Override
public void setPropertyValue(Object object, String propertyName, Object value) { public void setPropertyValue(Object object, String propertyName, Object value) {
final AttributeMapping attributeMapping = findSubPart( propertyName, this ).asAttributeMapping(); final AttributeMapping attributeMapping = findSubPart( propertyName, this ).asAttributeMapping();
final AttributeMetadata attributeMetadata = attributeMapping.getAttributeMetadata(); setterCache[attributeMapping.getStateArrayPosition()].set( object, value );
attributeMetadata.getPropertyAccess().getSetter().set( object, value );
} }
public static int getTableId(String tableName, String[] tables) { public static int getTableId(String tableName, String[] tables) {
@ -6013,6 +6016,15 @@ public abstract class AbstractEntityPersister
builder.add( am ); builder.add( am );
} }
this.attributeMappings = builder.build(); this.attributeMappings = builder.build();
final Getter[] getters = new Getter[attributeMappings.size()];
final Setter[] setters = new Setter[attributeMappings.size()];
for ( int i = 0; i < attributeMappings.size(); i++ ) {
final PropertyAccess propertyAccess = attributeMappings.get( i ).getAttributeMetadata().getPropertyAccess();
getters[i] = propertyAccess.getGetter();
setters[i] = propertyAccess.getSetter();
}
this.getterCache = getters;
this.setterCache = setters;
// subclasses? it depends on the usage // subclasses? it depends on the usage
} }

View File

@ -529,7 +529,7 @@ public interface EntityPersister extends EntityMappingType, EntityMutationTarget
else { else {
for ( int i = 0; i < getNumberOfAttributeMappings(); i++ ) { for ( int i = 0; i < getNumberOfAttributeMappings(); i++ ) {
final AttributeMapping attributeMapping = getAttributeMapping( i ); final AttributeMapping attributeMapping = getAttributeMapping( i );
final Object attributeValue = attributeMapping.getPropertyAccess().getGetter().get( domainValue ); final Object attributeValue = attributeMapping.getValue( domainValue );
span += attributeMapping.breakDownJdbcValues( span += attributeMapping.breakDownJdbcValues(
attributeValue, attributeValue,
offset + span, offset + span,

View File

@ -235,28 +235,22 @@ public class AnonymousTupleEmbeddableValuedModelPart implements EmbeddableValued
@Override @Override
public Object[] getValues(Object instance) { public Object[] getValues(Object instance) {
return existingModelPartContainer.getEmbeddableTypeDescriptor() return existingModelPartContainer.getEmbeddableTypeDescriptor().getValues( instance );
.getValues( instance );
} }
@Override @Override
public Object getValue(Object instance, int position) { public Object getValue(Object instance, int position) {
return existingModelPartContainer.getEmbeddableTypeDescriptor() return existingModelPartContainer.getEmbeddableTypeDescriptor().getValue( instance, position );
.getAttributeMapping( position )
.getValue( instance );
} }
@Override @Override
public void setValues(Object instance, Object[] resolvedValues) { public void setValues(Object instance, Object[] resolvedValues) {
existingModelPartContainer.getEmbeddableTypeDescriptor() existingModelPartContainer.getEmbeddableTypeDescriptor().setValues( instance, resolvedValues );
.setValues( instance, resolvedValues );
} }
@Override @Override
public void setValue(Object instance, int position, Object value) { public void setValue(Object instance, int position, Object value) {
existingModelPartContainer.getEmbeddableTypeDescriptor() existingModelPartContainer.getEmbeddableTypeDescriptor().setValue( instance, position, value );
.getAttributeMapping( position )
.setValue( instance, value );
} }
@Override @Override

View File

@ -198,9 +198,7 @@ public class AnonymousTupleEntityValuedModelPart
@Override @Override
public Object getValue(Object instance, int position) { public Object getValue(Object instance, int position) {
return delegate.getEntityMappingType() return delegate.getEntityMappingType().getValue( instance, position );
.getAttributeMapping( position )
.getValue( instance );
} }
@Override @Override
@ -210,9 +208,7 @@ public class AnonymousTupleEntityValuedModelPart
@Override @Override
public void setValue(Object instance, int position, Object value) { public void setValue(Object instance, int position, Object value) {
delegate.getEntityMappingType() delegate.getEntityMappingType().setValue( instance, position, value );
.getAttributeMapping( position )
.setValue( instance, value );
} }
@Override @Override

View File

@ -12,6 +12,7 @@ import java.util.Set;
import jakarta.persistence.CacheRetrieveMode; import jakarta.persistence.CacheRetrieveMode;
import jakarta.persistence.CacheStoreMode; import jakarta.persistence.CacheStoreMode;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.hibernate.CacheMode; import org.hibernate.CacheMode;
import org.hibernate.FlushMode; import org.hibernate.FlushMode;
@ -57,13 +58,13 @@ public interface QueryOptions {
* Transformer applied to the query to transform the structure of each "row" * Transformer applied to the query to transform the structure of each "row"
* in the results * in the results
*/ */
TupleTransformer<?> getTupleTransformer(); @Nullable TupleTransformer<?> getTupleTransformer();
/** /**
* Transformer applied to the query to transform the structure of the * Transformer applied to the query to transform the structure of the
* overall results * overall results
*/ */
ResultListTransformer<?> getResultListTransformer(); @Nullable ResultListTransformer<?> getResultListTransformer();
/** /**
* Should results from the query be cached? * Should results from the query be cached?

View File

@ -72,6 +72,7 @@ import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions;
import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
import org.hibernate.stat.spi.StatisticsImplementor; import org.hibernate.stat.spi.StatisticsImplementor;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import org.hibernate.type.descriptor.java.MutabilityPlan;
import org.checkerframework.checker.nullness.qual.EnsuresNonNull; import org.checkerframework.checker.nullness.qual.EnsuresNonNull;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
@ -124,6 +125,7 @@ public class EntityInitializerImpl extends AbstractInitializer<EntityInitializer
private final DomainResultAssembler<?>[][] assemblers; private final DomainResultAssembler<?>[][] assemblers;
private final Initializer<?>[][] subInitializers; private final Initializer<?>[][] subInitializers;
private final MutabilityPlan<Object>[][] updatableAttributeMutabilityPlans;
public static class EntityInitializerData extends InitializerData { public static class EntityInitializerData extends InitializerData {
@ -235,10 +237,13 @@ public class EntityInitializerImpl extends AbstractInitializer<EntityInitializer
final Collection<EntityMappingType> subMappingTypes = rootEntityDescriptor.getSubMappingTypes(); final Collection<EntityMappingType> subMappingTypes = rootEntityDescriptor.getSubMappingTypes();
final DomainResultAssembler<?>[][] assemblers = new DomainResultAssembler[subMappingTypes.size() + 1][]; final DomainResultAssembler<?>[][] assemblers = new DomainResultAssembler[subMappingTypes.size() + 1][];
final Initializer<?>[][] subInitializers = new Initializer<?>[subMappingTypes.size() + 1][]; final Initializer<?>[][] subInitializers = new Initializer<?>[subMappingTypes.size() + 1][];
final MutabilityPlan[][] updatableAttributeMutabilityPlans = new MutabilityPlan[subMappingTypes.size() + 1][];
assemblers[rootEntityDescriptor.getSubclassId()] = new DomainResultAssembler[rootEntityDescriptor.getNumberOfFetchables()]; assemblers[rootEntityDescriptor.getSubclassId()] = new DomainResultAssembler[rootEntityDescriptor.getNumberOfFetchables()];
updatableAttributeMutabilityPlans[rootEntityDescriptor.getSubclassId()] = new MutabilityPlan[rootEntityDescriptor.getNumberOfAttributeMappings()];
for ( EntityMappingType subMappingType : subMappingTypes ) { for ( EntityMappingType subMappingType : subMappingTypes ) {
assemblers[subMappingType.getSubclassId()] = new DomainResultAssembler[subMappingType.getNumberOfFetchables()]; assemblers[subMappingType.getSubclassId()] = new DomainResultAssembler[subMappingType.getNumberOfFetchables()];
updatableAttributeMutabilityPlans[subMappingType.getSubclassId()] = new MutabilityPlan[subMappingType.getNumberOfAttributeMappings()];
} }
final int size = entityDescriptor.getNumberOfFetchables(); final int size = entityDescriptor.getNumberOfFetchables();
@ -262,8 +267,13 @@ public class EntityInitializerImpl extends AbstractInitializer<EntityInitializer
} }
assemblers[subclassId][stateArrayPosition] = stateAssembler; assemblers[subclassId][stateArrayPosition] = stateAssembler;
final AttributeMetadata attributeMetadata = attributeMapping.getAttributeMetadata();
if ( attributeMetadata.isUpdatable() ) {
updatableAttributeMutabilityPlans[subclassId][stateArrayPosition] = attributeMetadata.getMutabilityPlan();
}
for ( EntityMappingType subMappingType : declaringType.getSubMappingTypes() ) { for ( EntityMappingType subMappingType : declaringType.getSubMappingTypes() ) {
assemblers[subMappingType.getSubclassId()][stateArrayPosition] = stateAssembler; assemblers[subMappingType.getSubclassId()][stateArrayPosition] = stateAssembler;
updatableAttributeMutabilityPlans[subMappingType.getSubclassId()][stateArrayPosition] = updatableAttributeMutabilityPlans[subclassId][stateArrayPosition];
if ( subInitializer != null ) { if ( subInitializer != null ) {
if ( subInitializers[subMappingType.getSubclassId()] == null ) { if ( subInitializers[subMappingType.getSubclassId()] == null ) {
subInitializers[subMappingType.getSubclassId()] = new Initializer<?>[size]; subInitializers[subMappingType.getSubclassId()] = new Initializer<?>[size];
@ -285,6 +295,7 @@ public class EntityInitializerImpl extends AbstractInitializer<EntityInitializer
this.assemblers = assemblers; this.assemblers = assemblers;
this.subInitializers = subInitializers; this.subInitializers = subInitializers;
this.updatableAttributeMutabilityPlans = updatableAttributeMutabilityPlans;
this.notFoundAction = notFoundAction; this.notFoundAction = notFoundAction;
this.keyAssembler = keyResult == null ? null : keyResult.createResultAssembler( this, creationState ); this.keyAssembler = keyResult == null ? null : keyResult.createResultAssembler( this, creationState );
@ -591,26 +602,18 @@ public class EntityInitializerImpl extends AbstractInitializer<EntityInitializer
return isResultInitializer; return isResultInitializer;
} }
private static void deepCopy(ManagedMappingType containerDescriptor, Object[] source, Object[] target) { private void deepCopy(EntityPersister containerDescriptor, Object[] source, Object[] target) {
final int numberOfAttributeMappings = containerDescriptor.getNumberOfAttributeMappings(); final MutabilityPlan<Object>[] updatableAttributeMutabilityPlan = updatableAttributeMutabilityPlans[containerDescriptor.getSubclassId()];
for ( int i = 0; i < numberOfAttributeMappings; i++ ) { for ( int i = 0; i < updatableAttributeMutabilityPlan.length; i++ ) {
final AttributeMapping attributeMapping = containerDescriptor.getAttributeMapping( i ); final Object sourceValue = source[i];
final AttributeMetadata attributeMetadata = attributeMapping.getAttributeMetadata(); if ( updatableAttributeMutabilityPlan[i] != null
if ( attributeMetadata.isUpdatable() ) { && sourceValue != LazyPropertyInitializer.UNFETCHED_PROPERTY
final int position = attributeMapping.getStateArrayPosition(); && sourceValue != PropertyAccessStrategyBackRefImpl.UNKNOWN ) {
target[position] = copy( attributeMetadata, source[position] ); target[i] = updatableAttributeMutabilityPlan[i].deepCopy( source[i] );
} }
} }
} }
@SuppressWarnings("unchecked")
private static Object copy(AttributeMetadata attributeMetadata, Object sourceValue) {
return sourceValue == LazyPropertyInitializer.UNFETCHED_PROPERTY
|| sourceValue == PropertyAccessStrategyBackRefImpl.UNKNOWN
? sourceValue
: attributeMetadata.getMutabilityPlan().deepCopy( sourceValue );
}
@Override @Override
public ModelPart getInitializedPart() { public ModelPart getInitializedPart() {
return referencedModelPart; return referencedModelPart;

View File

@ -183,11 +183,10 @@ class CompositeGeneratorBuilder {
for ( int i = 0; i < size; i++ ) { for ( int i = 0; i < size; i++ ) {
final Generator generator = generators.get(i); final Generator generator = generators.get(i);
if ( generator != null ) { if ( generator != null ) {
final AttributeMapping attributeMapping = descriptor.getAttributeMapping(i); final Object value = descriptor.getValue( currentValue, i );
final Object value = attributeMapping.getPropertyAccess().getGetter().get( currentValue );
final Object generatedValue = ((BeforeExecutionGenerator) generator) final Object generatedValue = ((BeforeExecutionGenerator) generator)
.generate( session, owner, value, eventType ); .generate( session, owner, value, eventType );
attributeMapping.getPropertyAccess().getSetter().set( currentValue, generatedValue ); descriptor.setValue( currentValue, i, generatedValue );
} }
} }
return currentValue; return currentValue;

View File

@ -417,7 +417,18 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
return ((Object[]) component)[i]; return ((Object[]) component)[i];
} }
else { else {
return embeddableTypeDescriptor().getValue( component, i ); final EmbeddableMappingType embeddableMappingType = embeddableTypeDescriptor();
if ( embeddableMappingType.isPolymorphic() ) {
final EmbeddableMappingType.ConcreteEmbeddableType concreteEmbeddableType = embeddableMappingType.findSubtypeBySubclass(
component.getClass().getName()
);
return concreteEmbeddableType.declaresAttribute( i )
? embeddableMappingType.getValue( component, i )
: null;
}
else {
return embeddableMappingType.getValue( component, i );
}
} }
} }

View File

@ -76,7 +76,7 @@ public class LazyProxyBytecodeEnhancementCollectionInitializationTest {
Parent parent = s.getReference( Parent.class, 1 ); Parent parent = s.getReference( Parent.class, 1 );
assertThat( Hibernate.isPropertyInitialized( parent, "children") ).isFalse(); assertThat( Hibernate.isPropertyInitialized( parent, "children") ).isFalse();
assertThat( s.unwrap( SessionImplementor.class ).getPersistenceContext().getCollectionEntries() ) assertThat( s.unwrap( SessionImplementor.class ).getPersistenceContext().getCollectionEntries() )
.isEmpty(); .isNullOrEmpty();
// Accessing a collection property on a lazy proxy initializes the property and instantiates the collection, // Accessing a collection property on a lazy proxy initializes the property and instantiates the collection,
// but does not initialize the collection. // but does not initialize the collection.