From c5bdec20b96a1179d70338644d8c2d5f1408001e Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Fri, 21 Mar 2014 09:59:04 -0500 Subject: [PATCH] HHH-9071 - Proxy narrowing loses the initialized state of the original proxy --- .../internal/StatefulPersistenceContext.java | 47 +++++++++---------- .../test/proxy/narrow/ProxyNarrowingTest.java | 3 +- 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/engine/internal/StatefulPersistenceContext.java b/hibernate-core/src/main/java/org/hibernate/engine/internal/StatefulPersistenceContext.java index dbac24cab2..c63d59fb48 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/internal/StatefulPersistenceContext.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/internal/StatefulPersistenceContext.java @@ -624,42 +624,39 @@ public class StatefulPersistenceContext implements PersistenceContext { throws HibernateException { final Class concreteProxyClass = persister.getConcreteProxyClass(); - final boolean alreadyNarrow = concreteProxyClass.isAssignableFrom( proxy.getClass() ); + final boolean alreadyNarrow = concreteProxyClass.isInstance( proxy ); if ( !alreadyNarrow ) { 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 ) { proxiesByKey.remove( key ); - //return the proxied 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; - HibernateProxy newHibernateProxy = (HibernateProxy) proxy; - - // set the read-only/modifiable mode in the new proxy to what it was in the original proxy - final boolean readOnlyOrig = originalHibernateProxy.getHibernateLazyInitializer().isReadOnly(); - newHibernateProxy.getHibernateLazyInitializer().setReadOnly( readOnlyOrig ); - - // if the original proxy is already initialized, initialize the new proxy - if ( !originalHibernateProxy.getHibernateLazyInitializer().isUninitialized() ) { - newHibernateProxy.getHibernateLazyInitializer().setImplementation( - originalHibernateProxy.getHibernateLazyInitializer().getImplementation() ); - } + // Similarly, if the original HibernateProxy is initialized, there + // is again no point in creating a proxy. Just return the impl + final HibernateProxy originalHibernateProxy = (HibernateProxy) proxy; + if ( !originalHibernateProxy.getHibernateLazyInitializer().isUninitialized() ) { + final Object impl = originalHibernateProxy.getHibernateLazyInitializer().getImplementation(); + // can we return it? + if ( concreteProxyClass.isInstance( impl ) ) { + proxiesByKey.remove( key ); + return impl; } - 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 { diff --git a/hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/ProxyNarrowingTest.java b/hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/ProxyNarrowingTest.java index 0794a2a3dc..7d3f6a2369 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/ProxyNarrowingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/proxy/narrow/ProxyNarrowingTest.java @@ -80,7 +80,8 @@ public class ProxyNarrowingTest extends BaseCoreFunctionalTestCase { ConcreteEntity concreteEntityProxy = (ConcreteEntity) session.load( ConcreteEntity.class, abstractEntityProxy.getId() ); // the new proxy created should be initialized - assertTrue( ( concreteEntityProxy instanceof HibernateProxy ) && Hibernate.isInitialized( concreteEntityProxy ) ); + assertTrue( Hibernate.isInitialized( concreteEntityProxy ) ); + assertTrue( session.contains( concreteEntityProxy ) ); } finally { session.close();