HHH-11147 - Integrate enhanced-proxy support with BatchFetchQueue

This commit is contained in:
Steve Ebersole 2019-06-27 08:27:51 -05:00 committed by Sanne Grinovero
parent 71b22a3258
commit 8148847ee1
8 changed files with 80 additions and 37 deletions

View File

@ -10,6 +10,7 @@ import org.hibernate.bytecode.enhance.spi.interceptor.BytecodeLazyAttributeInter
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributesMetadata;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
@ -36,6 +37,14 @@ public interface BytecodeEnhancementMetadata {
LazyAttributesMetadata getLazyAttributesMetadata();
/**
* Create an "enhancement as proxy" instance for the given entity
*
* @apiNote The `addEmptyEntry` parameter is used to avoid creation of `EntityEntry` instances when we
* do not need them. - mainly from StatelessSession
*/
PersistentAttributeInterceptable createEnhancedProxy(EntityKey keyToLoad, boolean addEmptyEntry, SharedSessionContractImplementor session);
/**
* Build and inject an interceptor instance into the enhanced entity.
*

View File

@ -746,6 +746,11 @@ public class StatefulPersistenceContext implements PersistenceContext {
return proxyFor( e.getPersister(), e.getEntityKey(), impl );
}
@Override
public void addEnhancedProxy(EntityKey key, PersistentAttributeInterceptable entity) {
entitiesByKey.put( key, entity );
}
@Override
public Object getCollectionOwner(Serializable key, CollectionPersister collectionPersister) throws MappingException {
// todo : we really just need to add a split in the notions of:

View File

@ -127,12 +127,12 @@ public class BatchFetchQueue {
*/
public void addBatchLoadableEntityKey(EntityKey key) {
if ( key.isBatchLoadable() ) {
LinkedHashSet<EntityKey> set = batchLoadableEntityKeys.get( key.getEntityName());
if (set == null) {
set = new LinkedHashSet<>( 8 );
batchLoadableEntityKeys.put( key.getEntityName(), set);
}
set.add(key);
final LinkedHashSet<EntityKey> keysForEntity = batchLoadableEntityKeys.computeIfAbsent(
key.getEntityName(),
k -> new LinkedHashSet<>( 8 )
);
keysForEntity.add( key );
}
}

View File

@ -344,6 +344,12 @@ public interface PersistenceContext {
*/
Object proxyFor(Object impl) throws HibernateException;
/**
* Cross between {@link #addEntity(EntityKey, Object)} and {@link #addProxy(EntityKey, Object)}
* for use with enhancement-as-proxy
*/
void addEnhancedProxy(EntityKey key, PersistentAttributeInterceptable entity);
/**
* Get the entity that owns this persistent collection
*/

View File

@ -313,31 +313,12 @@ public class DefaultLoadEventListener extends AbstractLockUpgradeEventListener i
}
}
// Potentially add a batch-fetch entry into the queue for this entity
persistenceContext.getBatchFetchQueue().addBatchLoadableEntityKey( keyToLoad );
// This is the crux of HHH-11147
// create the (uninitialized) entity instance - has only id set
final Object entity = persister.getEntityTuplizer().instantiate(
keyToLoad.getIdentifier(),
event.getSession()
);
// add the entity instance to the persistence context
persistenceContext.addEntity(
entity,
Status.MANAGED,
null,
keyToLoad,
null,
LockMode.NONE,
true,
persister,
true
);
persister.getEntityMetamodel()
.getBytecodeEnhancementMetadata()
.injectEnhancedEntityAsProxyInterceptor( entity, keyToLoad, event.getSession() );
return entity;
return persister.getBytecodeEnhancementMetadata().createEnhancedProxy( keyToLoad, true, event.getSession() );
}
else {
if ( persister.hasProxy() ) {

View File

@ -303,14 +303,7 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
// we cannot use bytecode proxy for entities with subclasses
if ( !persister.getEntityMetamodel().hasSubclasses() ) {
final Object entity = persister.getEntityTuplizer().instantiate( id, this );
persister.getEntityMetamodel()
.getBytecodeEnhancementMetadata()
.injectEnhancedEntityAsProxyInterceptor( entity, entityKey, this );
getPersistenceContext().addEntity( entityKey, entity );
return entity;
return persister.getBytecodeEnhancementMetadata().createEnhancedProxy( entityKey, false, this );
}
}

View File

@ -12,6 +12,7 @@ import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributesMetadata;
import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
import org.hibernate.bytecode.spi.NotInstrumentedException;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
@ -68,6 +69,11 @@ public class BytecodeEnhancementMetadataNonPojoImpl implements BytecodeEnhanceme
throw new NotInstrumentedException( errorMsg );
}
@Override
public PersistentAttributeInterceptable createEnhancedProxy(EntityKey keyToLoad, boolean addEmptyEntry, SharedSessionContractImplementor session) {
throw new NotInstrumentedException( errorMsg );
}
@Override
public LazyAttributeLoadingInterceptor extractInterceptor(Object entity) throws NotInstrumentedException {
throw new NotInstrumentedException( errorMsg );

View File

@ -6,9 +6,11 @@
*/
package org.hibernate.tuple.entity;
import java.io.Serializable;
import java.util.Set;
import java.util.function.Function;
import org.hibernate.LockMode;
import org.hibernate.bytecode.enhance.spi.interceptor.BytecodeLazyAttributeInterceptor;
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
@ -19,7 +21,9 @@ import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.engine.spi.Status;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.CompositeType;
/**
@ -130,6 +134,45 @@ public class BytecodeEnhancementMetadataPojoImpl implements BytecodeEnhancementM
return (LazyAttributeLoadingInterceptor) extractLazyInterceptor( entity );
}
@Override
public PersistentAttributeInterceptable createEnhancedProxy(EntityKey entityKey, boolean addEmptyEntry, SharedSessionContractImplementor session) {
final EntityPersister persister = entityKey.getPersister();
final Serializable identifier = entityKey.getIdentifier();
// first, instantiate the entity instance to use as the proxy
final PersistentAttributeInterceptable entity = (PersistentAttributeInterceptable) persister.getEntityTuplizer().instantiate( identifier, session );
// add the entity (proxy) instance to the PC
session.getPersistenceContext().addEnhancedProxy( entityKey, entity );
// if requested, add the "holder entry" to the PC
if ( addEmptyEntry ) {
session.getPersistenceContext().addEntry(
entity,
Status.MANAGED,
// loaded state
null,
// row-id
null,
identifier,
// version
null,
LockMode.NONE,
// we assume it exists in db
true,
persister,
true
);
}
// inject the interceptor
persister.getEntityMetamodel()
.getBytecodeEnhancementMetadata()
.injectEnhancedEntityAsProxyInterceptor( entity, entityKey, session );
return entity;
}
@Override
public LazyAttributeLoadingInterceptor injectInterceptor(
Object entity,