HHH-15649 Additional performance fixes relating to Klass's _secondary_super_cache interaction with entity enhancement

This commit is contained in:
Sanne Grinovero 2022-10-31 13:52:34 +00:00 committed by Sanne Grinovero
parent 3be1c2980c
commit dd7cbe8b89
13 changed files with 76 additions and 59 deletions

View File

@ -10,12 +10,9 @@ import java.util.Iterator;
import org.hibernate.bytecode.enhance.spi.interceptor.BytecodeLazyAttributeInterceptor;
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.HibernateIterator;
import org.hibernate.engine.internal.ManagedTypeHelper;
import org.hibernate.engine.jdbc.LobCreator;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
@ -23,6 +20,9 @@ import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import org.hibernate.collection.spi.LazyInitializable;
import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable;
import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable;
/**
* <ul>
* <li>Provides access to the full range of Hibernate built-in types. <tt>Type</tt>
@ -66,9 +66,8 @@ public final class Hibernate {
else if ( proxy instanceof LazyInitializable ) {
( (LazyInitializable) proxy ).forceInitialization();
}
else if ( proxy instanceof PersistentAttributeInterceptable ) {
final PersistentAttributeInterceptable interceptable = (PersistentAttributeInterceptable) proxy;
final PersistentAttributeInterceptor interceptor = interceptable.$$_hibernate_getInterceptor();
else if ( isPersistentAttributeInterceptable( proxy ) ) {
final PersistentAttributeInterceptor interceptor = asPersistentAttributeInterceptable( proxy ).$$_hibernate_getInterceptor();
if ( interceptor instanceof EnhancementAsProxyLazinessInterceptor ) {
( (EnhancementAsProxyLazinessInterceptor) interceptor ).forceInitialize( proxy, null );
}
@ -86,10 +85,8 @@ public final class Hibernate {
if ( proxy instanceof HibernateProxy ) {
return !( (HibernateProxy) proxy ).getHibernateLazyInitializer().isUninitialized();
}
else if ( ManagedTypeHelper.isPersistentAttributeInterceptable( proxy ) ) {
final PersistentAttributeInterceptable asPersistentAttributeInterceptable = ManagedTypeHelper.asPersistentAttributeInterceptable(
proxy );
final PersistentAttributeInterceptor interceptor = asPersistentAttributeInterceptable.$$_hibernate_getInterceptor();
else if ( isPersistentAttributeInterceptable( proxy ) ) {
final PersistentAttributeInterceptor interceptor = asPersistentAttributeInterceptable( proxy ).$$_hibernate_getInterceptor();
if ( interceptor instanceof EnhancementAsProxyLazinessInterceptor ) {
return false;
}
@ -204,8 +201,9 @@ public final class Hibernate {
entity = proxy;
}
if ( entity instanceof PersistentAttributeInterceptable ) {
PersistentAttributeInterceptor interceptor = ( (PersistentAttributeInterceptable) entity ).$$_hibernate_getInterceptor();
if ( isPersistentAttributeInterceptable( entity ) ) {
PersistentAttributeInterceptor interceptor = asPersistentAttributeInterceptable( entity ).$$_hibernate_getInterceptor();
if ( interceptor instanceof BytecodeLazyAttributeInterceptor ) {
return ( (BytecodeLazyAttributeInterceptor) interceptor ).isAttributeLoaded( propertyName );
}

View File

@ -17,11 +17,15 @@ import org.hibernate.LockMode;
import org.hibernate.bytecode.enhance.spi.CollectionTracker;
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.internal.ManagedTypeHelper;
import org.hibernate.engine.spi.SelfDirtinessTracker;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.engine.spi.Status;
import org.hibernate.persister.entity.EntityPersister;
import static org.hibernate.engine.internal.ManagedTypeHelper.asSelfDirtinessTracker;
import static org.hibernate.engine.internal.ManagedTypeHelper.isSelfDirtinessTracker;
/**
* Interceptor that loads attributes lazily
*
@ -155,13 +159,14 @@ public class LazyAttributeLoadingInterceptor extends AbstractLazyLoadInterceptor
}
private void takeCollectionSizeSnapshot(Object target, String fieldName, Object value) {
if ( value instanceof Collection && target instanceof SelfDirtinessTracker ) {
if ( value instanceof Collection && isSelfDirtinessTracker( target ) ) {
// This must be called first, so that we remember that there is a collection out there,
// even if we don't know its size (see below).
CollectionTracker tracker = ( (SelfDirtinessTracker) target ).$$_hibernate_getCollectionTracker();
final SelfDirtinessTracker trackerAsSDT = asSelfDirtinessTracker( target );
CollectionTracker tracker = trackerAsSDT.$$_hibernate_getCollectionTracker();
if ( tracker == null ) {
( (SelfDirtinessTracker) target ).$$_hibernate_clearDirtyAttributes();
tracker = ( (SelfDirtinessTracker) target ).$$_hibernate_getCollectionTracker();
trackerAsSDT.$$_hibernate_clearDirtyAttributes();
tracker = trackerAsSDT.$$_hibernate_getCollectionTracker();
}
if ( value instanceof PersistentCollection && !( (PersistentCollection) value ).wasInitialized() ) {

View File

@ -64,6 +64,14 @@ public final class ManagedTypeHelper {
return entity instanceof EnhancedEntity || entity instanceof Managed;
}
/**
* @param entity
* @return true if and only if the entity implements {@see ManagedEntity}
*/
public static boolean isManagedEntity(Object entity) {
return entity instanceof EnhancedEntity || entity instanceof ManagedEntity;
}
/**
* @param type
* @return true if and only if the type is assignable to a {@see PersistentAttributeInterceptable} type.
@ -176,4 +184,5 @@ public final class ManagedTypeHelper {
return (SelfDirtinessTracker) entity;
}
}
}

View File

@ -40,7 +40,6 @@ import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterc
import org.hibernate.cache.spi.access.NaturalIdDataAccess;
import org.hibernate.cache.spi.access.SoftLock;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.internal.ManagedTypeHelper;
import org.hibernate.engine.loading.internal.LoadContexts;
import org.hibernate.engine.spi.AssociationKey;
import org.hibernate.engine.spi.BatchFetchQueue;
@ -74,6 +73,9 @@ import org.hibernate.type.CollectionType;
import org.jboss.logging.Logger;
import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable;
import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable;
/**
* A <strong>stateful</strong> implementation of the {@link PersistenceContext} contract meaning that we maintain this
* state throughout the life of the persistence context.
@ -609,9 +611,8 @@ public class StatefulPersistenceContext implements PersistenceContext {
}
// or an uninitialized enhanced entity ("bytecode proxy")...
if ( value instanceof PersistentAttributeInterceptable ) {
final PersistentAttributeInterceptable bytecodeProxy = (PersistentAttributeInterceptable) value;
final BytecodeLazyAttributeInterceptor interceptor = (BytecodeLazyAttributeInterceptor) bytecodeProxy.$$_hibernate_getInterceptor();
if ( isPersistentAttributeInterceptable( value ) ) {
final BytecodeLazyAttributeInterceptor interceptor = (BytecodeLazyAttributeInterceptor) asPersistentAttributeInterceptable( value ).$$_hibernate_getInterceptor();
if ( interceptor != null ) {
interceptor.setSession( getSession() );
}
@ -677,9 +678,8 @@ public class StatefulPersistenceContext implements PersistenceContext {
//initialize + unwrap the object and return it
return li.getImplementation();
}
else if ( ManagedTypeHelper.isPersistentAttributeInterceptable( maybeProxy ) ) {
final PersistentAttributeInterceptable interceptable = ManagedTypeHelper.asPersistentAttributeInterceptable( maybeProxy );
final PersistentAttributeInterceptor interceptor = interceptable.$$_hibernate_getInterceptor();
else if ( isPersistentAttributeInterceptable( maybeProxy ) ) {
final PersistentAttributeInterceptor interceptor = asPersistentAttributeInterceptable( maybeProxy ).$$_hibernate_getInterceptor();
if ( interceptor instanceof EnhancementAsProxyLazinessInterceptor ) {
( (EnhancementAsProxyLazinessInterceptor) interceptor ).forceInitialize( maybeProxy, null );
}

View File

@ -17,6 +17,7 @@ import org.hibernate.action.internal.EntityInsertAction;
import org.hibernate.classic.Lifecycle;
import org.hibernate.engine.internal.Cascade;
import org.hibernate.engine.internal.CascadePoint;
import org.hibernate.engine.internal.ManagedTypeHelper;
import org.hibernate.engine.internal.Versioning;
import org.hibernate.engine.spi.CascadingAction;
import org.hibernate.engine.spi.EntityEntry;
@ -107,9 +108,7 @@ public abstract class AbstractSaveEventListener
boolean requiresImmediateIdAccess) {
callbackRegistry.preCreate( entity );
if ( entity instanceof SelfDirtinessTracker ) {
( (SelfDirtinessTracker) entity ).$$_hibernate_clearDirtyAttributes();
}
ManagedTypeHelper.processIfSelfDirtinessTracker( entity, SelfDirtinessTracker::$$_hibernate_clearDirtyAttributes );
EntityPersister persister = source.getEntityPersister( entityName, entity );
Serializable generatedId = persister.getIdentifierGenerator().generate( source, entity );

View File

@ -251,9 +251,7 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
return true;
}
else {
if ( SelfDirtinessTracker.class.isInstance( event.getEntity() ) ) {
( (SelfDirtinessTracker) event.getEntity() ).$$_hibernate_clearDirtyAttributes();
}
ManagedTypeHelper.processIfSelfDirtinessTracker( event.getEntity(), SelfDirtinessTracker::$$_hibernate_clearDirtyAttributes );
event.getSession()
.getFactory()
.getCustomEntityDirtinessStrategy()

View File

@ -17,12 +17,12 @@ import org.hibernate.WrongClassException;
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor;
import org.hibernate.engine.internal.Cascade;
import org.hibernate.engine.internal.CascadePoint;
import org.hibernate.engine.internal.ManagedTypeHelper;
import org.hibernate.engine.spi.CascadingAction;
import org.hibernate.engine.spi.CascadingActions;
import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
import org.hibernate.engine.spi.SelfDirtinessTracker;
import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -42,6 +42,10 @@ import org.hibernate.stat.spi.StatisticsImplementor;
import org.hibernate.type.ForeignKeyDirection;
import org.hibernate.type.TypeHelper;
import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable;
import static org.hibernate.engine.internal.ManagedTypeHelper.asSelfDirtinessTracker;
import static org.hibernate.engine.internal.ManagedTypeHelper.isSelfDirtinessTracker;
/**
* Defines the default copy event listener used by hibernate for copying entities
* in response to generated copy events.
@ -111,9 +115,8 @@ public class DefaultMergeEventListener extends AbstractSaveEventListener impleme
entity = li.getImplementation();
}
}
else if ( original instanceof PersistentAttributeInterceptable ) {
final PersistentAttributeInterceptable interceptable = (PersistentAttributeInterceptable) original;
final PersistentAttributeInterceptor interceptor = interceptable.$$_hibernate_getInterceptor();
else if ( ManagedTypeHelper.isPersistentAttributeInterceptable( original ) ) {
final PersistentAttributeInterceptor interceptor = asPersistentAttributeInterceptable( original ).$$_hibernate_getInterceptor();
if ( interceptor instanceof EnhancementAsProxyLazinessInterceptor ) {
final EnhancementAsProxyLazinessInterceptor proxyInterceptor = (EnhancementAsProxyLazinessInterceptor) interceptor;
LOG.trace( "Ignoring uninitialized enhanced-proxy" );
@ -249,9 +252,8 @@ public class DefaultMergeEventListener extends AbstractSaveEventListener impleme
event.setResult( copy );
if ( copy instanceof PersistentAttributeInterceptable ) {
final PersistentAttributeInterceptable interceptable = (PersistentAttributeInterceptable) copy;
final PersistentAttributeInterceptor interceptor = interceptable.$$_hibernate_getInterceptor();
if ( ManagedTypeHelper.isPersistentAttributeInterceptable( copy ) ) {
final PersistentAttributeInterceptor interceptor = asPersistentAttributeInterceptable( copy ).$$_hibernate_getInterceptor();
if ( interceptor == null ) {
persister.getBytecodeEnhancementMetadata().injectInterceptor( copy, id, session );
}
@ -363,11 +365,11 @@ public class DefaultMergeEventListener extends AbstractSaveEventListener impleme
return source.getPersistenceContextInternal().unproxy( managed );
}
if ( incoming instanceof PersistentAttributeInterceptable
if ( ManagedTypeHelper.isPersistentAttributeInterceptable( incoming )
&& persister.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading() ) {
final PersistentAttributeInterceptor incomingInterceptor = ( (PersistentAttributeInterceptable) incoming ).$$_hibernate_getInterceptor();
final PersistentAttributeInterceptor managedInterceptor = ( (PersistentAttributeInterceptable) managed ).$$_hibernate_getInterceptor();
final PersistentAttributeInterceptor incomingInterceptor = asPersistentAttributeInterceptable( incoming ).$$_hibernate_getInterceptor();
final PersistentAttributeInterceptor managedInterceptor = asPersistentAttributeInterceptable( managed ).$$_hibernate_getInterceptor();
// todo - do we need to specially handle the case where both `incoming` and `managed` are initialized, but
// with different attributes initialized?
@ -392,12 +394,13 @@ public class DefaultMergeEventListener extends AbstractSaveEventListener impleme
private void markInterceptorDirty(final Object entity, final Object target, EntityPersister persister) {
// for enhanced entities, copy over the dirty attributes
if ( entity instanceof SelfDirtinessTracker && target instanceof SelfDirtinessTracker ) {
if ( isSelfDirtinessTracker( entity ) && isSelfDirtinessTracker( target ) ) {
// clear, because setting the embedded attributes dirties them
( (SelfDirtinessTracker) target ).$$_hibernate_clearDirtyAttributes();
final SelfDirtinessTracker castedTarget = asSelfDirtinessTracker( target );
castedTarget.$$_hibernate_clearDirtyAttributes();
for ( String fieldName : ( (SelfDirtinessTracker) entity ).$$_hibernate_getDirtyAttributes() ) {
( (SelfDirtinessTracker) target ).$$_hibernate_trackChange( fieldName );
for ( String fieldName : asSelfDirtinessTracker( entity ).$$_hibernate_getDirtyAttributes() ) {
castedTarget.$$_hibernate_trackChange( fieldName );
}
}
}

View File

@ -9,6 +9,7 @@ package org.hibernate.event.internal;
import org.hibernate.HibernateException;
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.internal.ManagedTypeHelper;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.event.spi.EventSource;
@ -31,8 +32,8 @@ public class DirtyCollectionSearchVisitor extends AbstractVisitor {
public DirtyCollectionSearchVisitor(Object entity, EventSource session, boolean[] propertyVersionability) {
super( session );
EnhancementAsProxyLazinessInterceptor interceptor = null;
if ( entity instanceof PersistentAttributeInterceptable ) {
if ( ( (PersistentAttributeInterceptable) entity ).$$_hibernate_getInterceptor() instanceof EnhancementAsProxyLazinessInterceptor ) {
if ( ManagedTypeHelper.isPersistentAttributeInterceptable( entity ) ) {
if ( ManagedTypeHelper.asPersistentAttributeInterceptable( entity ).$$_hibernate_getInterceptor() instanceof EnhancementAsProxyLazinessInterceptor ) {
interceptor = (EnhancementAsProxyLazinessInterceptor) ( (PersistentAttributeInterceptable) entity ).$$_hibernate_getInterceptor();
}
}

View File

@ -13,6 +13,7 @@ import org.hibernate.HibernateException;
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.internal.ManagedTypeHelper;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.engine.spi.SessionImplementor;
@ -107,8 +108,8 @@ public class WrapVisitor extends ProxyVisitor {
return null;
}
else {
if ( entity instanceof PersistentAttributeInterceptable ) {
if ( ( (PersistentAttributeInterceptable) entity ).$$_hibernate_getInterceptor() instanceof EnhancementAsProxyLazinessInterceptor ) {
if ( ManagedTypeHelper.isPersistentAttributeInterceptable( entity ) ) {
if ( ManagedTypeHelper.asPersistentAttributeInterceptable( entity ).$$_hibernate_getInterceptor() instanceof EnhancementAsProxyLazinessInterceptor ) {
return null;
}
}

View File

@ -12,6 +12,7 @@ import javax.persistence.spi.LoadState;
import org.hibernate.Hibernate;
import org.hibernate.MappingException;
import org.hibernate.engine.internal.ManagedTypeHelper;
import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.ManagedEntity;
import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -70,8 +71,8 @@ public class PersistenceUnitUtilImpl implements PersistenceUnitUtil, Serializabl
if ( entity instanceof HibernateProxy ) {
return ((HibernateProxy) entity).getHibernateLazyInitializer().getInternalIdentifier();
}
else if ( entity instanceof ManagedEntity ) {
EntityEntry entityEntry = ((ManagedEntity) entity).$$_hibernate_getEntityEntry();
else if ( ManagedTypeHelper.isManagedEntity( entity ) ) {
EntityEntry entityEntry = ManagedTypeHelper.asManagedEntity( entity ).$$_hibernate_getEntityEntry();
if ( entityEntry != null ) {
return entityEntry.getId();
}

View File

@ -20,9 +20,7 @@ import java.util.WeakHashMap;
import javax.persistence.spi.LoadState;
import org.hibernate.HibernateException;
import org.hibernate.bytecode.enhance.spi.interceptor.AbstractLazyLoadInterceptor;
import org.hibernate.bytecode.enhance.spi.interceptor.BytecodeLazyAttributeInterceptor;
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
@ -30,6 +28,9 @@ import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable;
import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable;
/**
* Central delegate for handling calls from:<ul>
* <li>{@link javax.persistence.PersistenceUtil#isLoaded(Object)}</li>
@ -82,8 +83,8 @@ public final class PersistenceUtilHelper {
final boolean isInitialized = !( (HibernateProxy) reference ).getHibernateLazyInitializer().isUninitialized();
return isInitialized ? LoadState.LOADED : LoadState.NOT_LOADED;
}
else if ( reference instanceof PersistentAttributeInterceptable ) {
boolean isInitialized = isInitialized( (PersistentAttributeInterceptable) reference );
else if ( isPersistentAttributeInterceptable( reference ) ) {
boolean isInitialized = isInitialized( asPersistentAttributeInterceptable( reference ) );
return isInitialized ? LoadState.LOADED : LoadState.NOT_LOADED;
}
else if ( reference instanceof PersistentCollection ) {
@ -130,9 +131,10 @@ public final class PersistenceUtilHelper {
sureFromUs = true;
}
// we are instrumenting but we can't assume we are the only ones
if ( entity instanceof PersistentAttributeInterceptable ) {
final BytecodeLazyAttributeInterceptor interceptor = extractInterceptor( (PersistentAttributeInterceptable) entity );
if ( isPersistentAttributeInterceptable( entity ) ) {
final BytecodeLazyAttributeInterceptor interceptor = extractInterceptor( asPersistentAttributeInterceptable( entity ) );
final boolean isInitialized = interceptor == null || interceptor.isAttributeLoaded( attributeName );
LoadState state;
if (isInitialized && interceptor != null) {

View File

@ -16,6 +16,7 @@ import org.hibernate.cache.spi.entry.CacheEntry;
import org.hibernate.cache.spi.entry.ReferenceCacheEntryImpl;
import org.hibernate.cache.spi.entry.StandardCacheEntryImpl;
import org.hibernate.engine.internal.CacheHelper;
import org.hibernate.engine.internal.ManagedTypeHelper;
import org.hibernate.engine.internal.StatefulPersistenceContext;
import org.hibernate.engine.internal.TwoPhaseLoad;
import org.hibernate.engine.internal.Versioning;
@ -242,7 +243,7 @@ public class CacheEntityLoaderHelper extends AbstractLockUpgradeEventListener {
// make it circular-reference safe
final StatefulPersistenceContext statefulPersistenceContext = (StatefulPersistenceContext) session.getPersistenceContext();
if ( ( entity instanceof ManagedEntity ) ) {
if ( ManagedTypeHelper.isManagedEntity( entity ) ) {
statefulPersistenceContext.addReferenceEntry(
entity,
Status.READ_ONLY

View File

@ -149,9 +149,8 @@ public final class BytecodeEnhancementMetadataPojoImpl implements BytecodeEnhanc
.instantiate( identifier, session );
// clear the fields that are marked as dirty in the dirtiness tracker
if ( entity instanceof SelfDirtinessTracker ) {
( (SelfDirtinessTracker) entity ).$$_hibernate_clearDirtyAttributes();
}
ManagedTypeHelper.processIfSelfDirtinessTracker( entity, SelfDirtinessTracker::$$_hibernate_clearDirtyAttributes );
// add the entity (proxy) instance to the PC
persistenceContext.addEnhancedProxy( entityKey, entity );