HHH-13633 : Bugs join-fetching a collection when scrolling with a stateless session using enhancement as proxy

This commit is contained in:
Gail Badner 2019-09-19 23:08:23 -07:00
parent 9ad427a33e
commit b589251166
1 changed files with 53 additions and 13 deletions

View File

@ -46,6 +46,7 @@ import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.OuterJoinLoadable; import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.pretty.MessageHelper; import org.hibernate.pretty.MessageHelper;
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import org.hibernate.query.spi.ScrollableResultsImplementor; import org.hibernate.query.spi.ScrollableResultsImplementor;
import org.hibernate.tuple.entity.EntityMetamodel; import org.hibernate.tuple.entity.EntityMetamodel;
@ -298,28 +299,61 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
// caller did not request forceful eager loading, see if we can create // caller did not request forceful eager loading, see if we can create
// some form of proxy // some form of proxy
final boolean allowBytecodeProxy = getFactory()
.getSessionFactoryOptions()
.isEnhancementAsProxyEnabled();
final boolean entityHasHibernateProxyFactory = persister.getEntityMetamodel()
.getTuplizer()
.getProxyFactory() != null;
// first, check to see if we can use "bytecode proxies" // first, check to see if we can use "bytecode proxies"
final EntityMetamodel entityMetamodel = persister.getEntityMetamodel(); final EntityMetamodel entityMetamodel = persister.getEntityMetamodel();
final BytecodeEnhancementMetadata bytecodeEnhancementMetadata = entityMetamodel.getBytecodeEnhancementMetadata(); final BytecodeEnhancementMetadata bytecodeEnhancementMetadata = entityMetamodel.getBytecodeEnhancementMetadata();
if ( allowBytecodeProxy && bytecodeEnhancementMetadata.isEnhancedForLazyLoading() ) { if ( allowBytecodeProxy && bytecodeEnhancementMetadata.isEnhancedForLazyLoading() ) {
// we cannot use bytecode proxy for entities with subclasses // if the entity defines a HibernateProxy factory, see if there is an
// existing proxy associated with the PC - and if so, use it
if ( entityHasHibernateProxyFactory ) {
final PersistenceContext persistenceContext = getPersistenceContext();
final Object proxy = persistenceContext.getProxy( entityKey );
if ( proxy != null ) {
LOG.trace( "Entity proxy found in session cache" );
final LazyInitializer li = ( (HibernateProxy) proxy ).getHibernateLazyInitializer();
if ( li.isUnwrap() ) {
return li.getImplementation();
}
return persistenceContext.narrowProxy( proxy, persister, entityKey, null );
}
// specialized handling for entities with subclasses with a HibernateProxy factory
if ( persister.getEntityMetamodel().hasSubclasses() ) {
// entities with subclasses that define a ProxyFactory can create
// a HibernateProxy.
LOG.debugf( "Creating a HibernateProxy for to-one association with subclasses to honor laziness" );
return createProxy( entityKey );
}
return bytecodeEnhancementMetadata.createEnhancedProxy( entityKey, false, this );
}
else {
if ( !entityMetamodel.hasSubclasses() ) { if ( !entityMetamodel.hasSubclasses() ) {
return bytecodeEnhancementMetadata.createEnhancedProxy( entityKey, false, this ); return bytecodeEnhancementMetadata.createEnhancedProxy( entityKey, false, this );
} }
} }
}
// we could not use bytecode proxy, check to see if we can use HibernateProxy else {
if ( persister.hasProxy() ) { if ( persister.hasProxy() ) {
final Object existingProxy = getPersistenceContext().getProxy( entityKey ); final Object existingProxy = getPersistenceContext().getProxy( entityKey );
if ( existingProxy != null ) { if ( existingProxy != null ) {
return getPersistenceContext().narrowProxy( existingProxy, persister, entityKey, null ); return getPersistenceContext().narrowProxy( existingProxy, persister, entityKey, null );
} }
else { else {
final Object proxy = persister.createProxy( id, this ); return createProxy( entityKey );
getPersistenceContext().addProxy( entityKey, proxy ); }
return proxy;
} }
} }
} }
@ -328,6 +362,12 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
return get( entityName, id ); return get( entityName, id );
} }
private Object createProxy(EntityKey entityKey) {
final Object proxy = entityKey.getPersister().createProxy( entityKey.getIdentifier(), this );
getPersistenceContext().addProxy( entityKey, proxy );
return proxy;
}
@Override @Override
public Iterator iterate(String query, QueryParameters queryParameters) throws HibernateException { public Iterator iterate(String query, QueryParameters queryParameters) throws HibernateException {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();