HHH-9071 - Proxy narrowing loses the initialized state of the original proxy

This commit is contained in:
Steve Ebersole 2014-03-21 09:59:04 -05:00
parent 2cf52cc7f1
commit c5bdec20b9
2 changed files with 24 additions and 26 deletions

View File

@ -624,42 +624,39 @@ public class StatefulPersistenceContext implements PersistenceContext {
throws HibernateException { throws HibernateException {
final Class concreteProxyClass = persister.getConcreteProxyClass(); final Class concreteProxyClass = persister.getConcreteProxyClass();
final boolean alreadyNarrow = concreteProxyClass.isAssignableFrom( proxy.getClass() ); final boolean alreadyNarrow = concreteProxyClass.isInstance( proxy );
if ( !alreadyNarrow ) { if ( !alreadyNarrow ) {
LOG.narrowingProxy( concreteProxyClass ); LOG.narrowingProxy( concreteProxyClass );
// If an impl is passed, there is really no point in creating a proxy.
// It would just be extra processing. Just return the impl
if ( object != null ) { if ( object != null ) {
proxiesByKey.remove( key ); proxiesByKey.remove( key );
//return the proxied object
return object; return object;
} }
else {
proxy = persister.createProxy( key.getIdentifier(), session );
//overwrite old proxy
final Object proxyOrig = proxiesByKey.put( key, proxy );
if ( proxyOrig != null ) {
if ( ! ( proxyOrig instanceof HibernateProxy ) ) {
throw new AssertionFailure(
"proxy not of type HibernateProxy; it is " + proxyOrig.getClass()
);
}
HibernateProxy originalHibernateProxy = (HibernateProxy) proxyOrig; // Similarly, if the original HibernateProxy is initialized, there
HibernateProxy newHibernateProxy = (HibernateProxy) proxy; // is again no point in creating a proxy. Just return the impl
final HibernateProxy originalHibernateProxy = (HibernateProxy) proxy;
// set the read-only/modifiable mode in the new proxy to what it was in the original proxy if ( !originalHibernateProxy.getHibernateLazyInitializer().isUninitialized() ) {
final boolean readOnlyOrig = originalHibernateProxy.getHibernateLazyInitializer().isReadOnly(); final Object impl = originalHibernateProxy.getHibernateLazyInitializer().getImplementation();
newHibernateProxy.getHibernateLazyInitializer().setReadOnly( readOnlyOrig ); // can we return it?
if ( concreteProxyClass.isInstance( impl ) ) {
// if the original proxy is already initialized, initialize the new proxy proxiesByKey.remove( key );
if ( !originalHibernateProxy.getHibernateLazyInitializer().isUninitialized() ) { return impl;
newHibernateProxy.getHibernateLazyInitializer().setImplementation(
originalHibernateProxy.getHibernateLazyInitializer().getImplementation() );
}
} }
return proxy;
} }
// Otherwise, create the narrowed proxy
final HibernateProxy narrowedProxy = (HibernateProxy) persister.createProxy( key.getIdentifier(), session );
// set the read-only/modifiable mode in the new proxy to what it was in the original proxy
final boolean readOnlyOrig = originalHibernateProxy.getHibernateLazyInitializer().isReadOnly();
narrowedProxy.getHibernateLazyInitializer().setReadOnly( readOnlyOrig );
return narrowedProxy;
} }
else { else {

View File

@ -80,7 +80,8 @@ public class ProxyNarrowingTest extends BaseCoreFunctionalTestCase {
ConcreteEntity concreteEntityProxy = (ConcreteEntity) session.load( ConcreteEntity.class, abstractEntityProxy.getId() ); ConcreteEntity concreteEntityProxy = (ConcreteEntity) session.load( ConcreteEntity.class, abstractEntityProxy.getId() );
// the new proxy created should be initialized // the new proxy created should be initialized
assertTrue( ( concreteEntityProxy instanceof HibernateProxy ) && Hibernate.isInitialized( concreteEntityProxy ) ); assertTrue( Hibernate.isInitialized( concreteEntityProxy ) );
assertTrue( session.contains( concreteEntityProxy ) );
} }
finally { finally {
session.close(); session.close();