HHH-15790 Make HibernateProxy also type-cache friendly

This commit is contained in:
Sanne Grinovero 2022-11-29 23:43:44 +00:00 committed by Sanne Grinovero
parent 366a1e9c1d
commit fbf469830c
44 changed files with 482 additions and 212 deletions

View File

@ -35,7 +35,9 @@
import org.hibernate.proxy.LazyInitializer; import org.hibernate.proxy.LazyInitializer;
import org.hibernate.collection.spi.LazyInitializable; import org.hibernate.collection.spi.LazyInitializable;
import static org.hibernate.engine.internal.ManagedTypeHelper.asHibernateProxy;
import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable; import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable;
import static org.hibernate.engine.internal.ManagedTypeHelper.isHibernateProxy;
import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable; import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable;
/** /**
@ -126,8 +128,8 @@ public static void initialize(Object proxy) throws HibernateException {
return; return;
} }
if ( proxy instanceof HibernateProxy ) { if ( isHibernateProxy( proxy ) ) {
( (HibernateProxy) proxy ).getHibernateLazyInitializer().initialize(); asHibernateProxy( proxy ).getHibernateLazyInitializer().initialize();
} }
else if ( proxy instanceof LazyInitializable ) { else if ( proxy instanceof LazyInitializable ) {
( (LazyInitializable) proxy ).forceInitialization(); ( (LazyInitializable) proxy ).forceInitialization();
@ -149,8 +151,9 @@ else if ( isPersistentAttributeInterceptable( proxy ) ) {
* @return true if the argument is already initialized, or is not a proxy or collection * @return true if the argument is already initialized, or is not a proxy or collection
*/ */
public static boolean isInitialized(Object proxy) { public static boolean isInitialized(Object proxy) {
if ( proxy instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( proxy );
return !( (HibernateProxy) proxy ).getHibernateLazyInitializer().isUninitialized(); if ( lazyInitializer != null ) {
return !lazyInitializer.isUninitialized();
} }
else if ( isPersistentAttributeInterceptable( proxy ) ) { else if ( isPersistentAttributeInterceptable( proxy ) ) {
final PersistentAttributeInterceptor interceptor = asPersistentAttributeInterceptable( proxy ).$$_hibernate_getInterceptor(); final PersistentAttributeInterceptor interceptor = asPersistentAttributeInterceptable( proxy ).$$_hibernate_getInterceptor();
@ -241,8 +244,9 @@ public static <T> T get(List<T> list, int key) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T> Class<? extends T> getClass(T proxy) { public static <T> Class<? extends T> getClass(T proxy) {
Class<?> result; Class<?> result;
if ( proxy instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( proxy );
result = ( (HibernateProxy) proxy ).getHibernateLazyInitializer() if ( lazyInitializer != null ) {
result = lazyInitializer
.getImplementation() .getImplementation()
.getClass(); .getClass();
} }
@ -280,13 +284,13 @@ public static boolean isInstance(Object proxy, Class<?> entityClass) {
*/ */
public static boolean isPropertyInitialized(Object proxy, String propertyName) { public static boolean isPropertyInitialized(Object proxy, String propertyName) {
final Object entity; final Object entity;
if ( proxy instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( proxy );
final LazyInitializer li = ( (HibernateProxy) proxy ).getHibernateLazyInitializer(); if ( lazyInitializer != null ) {
if ( li.isUninitialized() ) { if ( lazyInitializer.isUninitialized() ) {
return false; return false;
} }
else { else {
entity = li.getImplementation(); entity = lazyInitializer.getImplementation();
} }
} }
else { else {
@ -315,8 +319,8 @@ public static boolean isPropertyInitialized(Object proxy, String propertyName) {
* uninitialized proxy that is not associated with an open session. * uninitialized proxy that is not associated with an open session.
*/ */
public static Object unproxy(Object proxy) { public static Object unproxy(Object proxy) {
if ( proxy instanceof HibernateProxy ) { if ( isHibernateProxy( proxy ) ) {
HibernateProxy hibernateProxy = (HibernateProxy) proxy; HibernateProxy hibernateProxy = asHibernateProxy( proxy );
LazyInitializer initializer = hibernateProxy.getHibernateLazyInitializer(); LazyInitializer initializer = hibernateProxy.getHibernateLazyInitializer();
return initializer.getImplementation(); return initializer.getImplementation();
} }

View File

@ -6,6 +6,7 @@
*/ */
package org.hibernate.bytecode.internal.bytebuddy; package org.hibernate.bytecode.internal.bytebuddy;
import static net.bytebuddy.matcher.ElementMatchers.anyOf;
import static net.bytebuddy.matcher.ElementMatchers.isFinalizer; import static net.bytebuddy.matcher.ElementMatchers.isFinalizer;
import static net.bytebuddy.matcher.ElementMatchers.isSynthetic; import static net.bytebuddy.matcher.ElementMatchers.isSynthetic;
import static net.bytebuddy.matcher.ElementMatchers.isVirtual; import static net.bytebuddy.matcher.ElementMatchers.isVirtual;
@ -26,6 +27,7 @@
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.bytecode.enhance.spi.EnhancerConstants; import org.hibernate.bytecode.enhance.spi.EnhancerConstants;
import org.hibernate.bytecode.spi.BasicProxyFactory; import org.hibernate.bytecode.spi.BasicProxyFactory;
import org.hibernate.engine.spi.PrimeAmongSecondarySupertypes;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.securitymanager.SystemSecurityManager; import org.hibernate.internal.util.securitymanager.SystemSecurityManager;
import org.hibernate.proxy.ProxyConfiguration; import org.hibernate.proxy.ProxyConfiguration;

View File

@ -34,6 +34,7 @@
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable; import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable;
import static org.hibernate.engine.internal.ManagedTypeHelper.isHibernateProxy;
import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable; import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable;
/** /**
@ -347,9 +348,8 @@ private boolean isUnequivocallyNonDirty(Object entity) {
return !enhancementAsProxyLazinessInterceptor.hasWrittenFieldNames(); return !enhancementAsProxyLazinessInterceptor.hasWrittenFieldNames();
} }
} }
else if ( entity instanceof HibernateProxy ) { else if ( isHibernateProxy( entity ) ) {
uninitializedProxy = ( (HibernateProxy) entity ).getHibernateLazyInitializer() uninitializedProxy = HibernateProxy.extractLazyInitializer( entity ).isUninitialized();
.isUninitialized();
} }
// we never have to check an uninitialized proxy // we never have to check an uninitialized proxy
return uninitializedProxy || !persister.hasCollections() return uninitializedProxy || !persister.hasCollections()

View File

@ -21,6 +21,8 @@
import org.hibernate.type.EntityType; import org.hibernate.type.EntityType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import static org.hibernate.engine.internal.ManagedTypeHelper.isHibernateProxy;
/** /**
* Algorithms related to foreign key constraint transparency * Algorithms related to foreign key constraint transparency
* *
@ -198,20 +200,20 @@ private boolean isNullifiable(final String entityName, Object object)
final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
if ( object instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( object );
if ( lazyInitializer != null ) {
// if it's an uninitialized proxy it can only be // if it's an uninitialized proxy it can only be
// transient if we did an unloaded-delete on the // transient if we did an unloaded-delete on the
// proxy itself, in which case there is no entry // proxy itself, in which case there is no entry
// for it, but its key has already been registered // for it, but its key has already been registered
// as nullifiable // as nullifiable
final LazyInitializer li = ( (HibernateProxy) object ).getHibernateLazyInitializer(); Object entity = lazyInitializer.getImplementation( session );
Object entity = li.getImplementation( session );
if ( entity == null ) { if ( entity == null ) {
return persistenceContext.containsDeletedUnloadedEntityKey( return persistenceContext.containsDeletedUnloadedEntityKey(
session.generateEntityKey( session.generateEntityKey(
li.getIdentifier(), lazyInitializer.getIdentifier(),
session.getFactory().getRuntimeMetamodels().getMappingMetamodel() session.getFactory().getRuntimeMetamodels().getMappingMetamodel()
.getEntityDescriptor( li.getEntityName() ) .getEntityDescriptor( lazyInitializer.getEntityName() )
) )
); );
} }
@ -255,7 +257,7 @@ private boolean isNullifiable(final String entityName, Object object)
* @return {@code true} if the given entity is not transient (meaning it is either detached/persistent) * @return {@code true} if the given entity is not transient (meaning it is either detached/persistent)
*/ */
public static boolean isNotTransient(String entityName, Object entity, Boolean assumed, SharedSessionContractImplementor session) { public static boolean isNotTransient(String entityName, Object entity, Boolean assumed, SharedSessionContractImplementor session) {
return entity instanceof HibernateProxy return isHibernateProxy( entity )
|| session.getPersistenceContextInternal().isEntryFor( entity ) || session.getPersistenceContextInternal().isEntryFor( entity )
// todo : shouldn't assumed be reversed here? // todo : shouldn't assumed be reversed here?
|| !isTransient( entityName, entity, assumed, session ); || !isTransient( entityName, entity, assumed, session );

View File

@ -14,6 +14,7 @@
import org.hibernate.engine.spi.ManagedMappedSuperclass; import org.hibernate.engine.spi.ManagedMappedSuperclass;
import org.hibernate.engine.spi.PersistentAttributeInterceptable; import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.engine.spi.SelfDirtinessTracker; import org.hibernate.engine.spi.SelfDirtinessTracker;
import org.hibernate.proxy.HibernateProxy;
import java.util.Objects; import java.util.Objects;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
@ -106,6 +107,18 @@ public static boolean isManagedEntity(final Object entity) {
return false; return false;
} }
/**
* @param entity
* @return true if and only if the entity implements {@see HibernateProxy}
*/
public static boolean isHibernateProxy(final Object entity) {
if ( entity instanceof PrimeAmongSecondarySupertypes ) {
PrimeAmongSecondarySupertypes t = (PrimeAmongSecondarySupertypes) entity;
return t.asHibernateProxy() != null;
}
return false;
}
/** /**
* @param entity * @param entity
* @return true if and only if the entity implements {@see PersistentAttributeInterceptable} * @return true if and only if the entity implements {@see PersistentAttributeInterceptable}

View File

@ -68,8 +68,10 @@
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import static org.hibernate.engine.internal.ManagedTypeHelper.asHibernateProxy;
import static org.hibernate.engine.internal.ManagedTypeHelper.asManagedEntity; import static org.hibernate.engine.internal.ManagedTypeHelper.asManagedEntity;
import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable; import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable;
import static org.hibernate.engine.internal.ManagedTypeHelper.isHibernateProxy;
import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable; import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable;
/** /**
@ -228,7 +230,7 @@ public void clear() {
if ( proxiesByKey != null ) { if ( proxiesByKey != null ) {
proxiesByKey.forEach( (k,o) -> { proxiesByKey.forEach( (k,o) -> {
if ( o != null) { if ( o != null) {
((HibernateProxy) o).getHibernateLazyInitializer().unsetSession(); HibernateProxy.extractLazyInitializer( o ).unsetSession();
} }
} ); } );
} }
@ -600,8 +602,8 @@ public boolean reassociateIfUninitializedProxy(Object value) throws MappingExcep
if ( ! Hibernate.isInitialized( value ) ) { if ( ! Hibernate.isInitialized( value ) ) {
// could be a proxy.... // could be a proxy....
if ( value instanceof HibernateProxy ) { if ( isHibernateProxy( value ) ) {
final HibernateProxy proxy = (HibernateProxy) value; final HibernateProxy proxy = asHibernateProxy( value );
final LazyInitializer li = proxy.getHibernateLazyInitializer(); final LazyInitializer li = proxy.getHibernateLazyInitializer();
reassociateProxy( li, proxy ); reassociateProxy( li, proxy );
return true; return true;
@ -624,9 +626,9 @@ public boolean reassociateIfUninitializedProxy(Object value) throws MappingExcep
@Override @Override
public void reassociateProxy(Object value, Object id) throws MappingException { public void reassociateProxy(Object value, Object id) throws MappingException {
if ( value instanceof HibernateProxy ) { if ( isHibernateProxy( value ) ) {
LOG.debugf( "Setting proxy identifier: %s", id ); LOG.debugf( "Setting proxy identifier: %s", id );
final HibernateProxy proxy = (HibernateProxy) value; final HibernateProxy proxy = asHibernateProxy( value );
final LazyInitializer li = proxy.getHibernateLazyInitializer(); final LazyInitializer li = proxy.getHibernateLazyInitializer();
li.setIdentifier( id ); li.setIdentifier( id );
reassociateProxy( li, proxy ); reassociateProxy( li, proxy );
@ -654,8 +656,8 @@ private void reassociateProxy(LazyInitializer li, HibernateProxy proxy) {
@Override @Override
public Object unproxy(Object maybeProxy) throws HibernateException { public Object unproxy(Object maybeProxy) throws HibernateException {
if ( maybeProxy instanceof HibernateProxy ) { if ( isHibernateProxy( maybeProxy ) ) {
final HibernateProxy proxy = (HibernateProxy) maybeProxy; final HibernateProxy proxy = asHibernateProxy( maybeProxy );
final LazyInitializer li = proxy.getHibernateLazyInitializer(); final LazyInitializer li = proxy.getHibernateLazyInitializer();
if ( li.isUninitialized() ) { if ( li.isUninitialized() ) {
throw new PersistentObjectException( throw new PersistentObjectException(
@ -672,8 +674,8 @@ public Object unproxy(Object maybeProxy) throws HibernateException {
@Override @Override
public Object unproxyAndReassociate(Object maybeProxy) throws HibernateException { public Object unproxyAndReassociate(Object maybeProxy) throws HibernateException {
if ( maybeProxy instanceof HibernateProxy ) { if ( isHibernateProxy( maybeProxy ) ) {
final HibernateProxy proxy = (HibernateProxy) maybeProxy; final HibernateProxy proxy = asHibernateProxy( maybeProxy );
final LazyInitializer li = proxy.getHibernateLazyInitializer(); final LazyInitializer li = proxy.getHibernateLazyInitializer();
reassociateProxy( li, proxy ); reassociateProxy( li, proxy );
//initialize + unwrap the object and return it //initialize + unwrap the object and return it
@ -722,7 +724,7 @@ public Object narrowProxy(Object proxy, EntityPersister persister, EntityKey key
// Similarly, if the original HibernateProxy is initialized, there // Similarly, if the original HibernateProxy is initialized, there
// is again no point in creating a proxy. Just return the impl // is again no point in creating a proxy. Just return the impl
final HibernateProxy originalHibernateProxy = (HibernateProxy) proxy; final HibernateProxy originalHibernateProxy = asHibernateProxy( proxy );
if ( !originalHibernateProxy.getHibernateLazyInitializer().isUninitialized() ) { if ( !originalHibernateProxy.getHibernateLazyInitializer().isUninitialized() ) {
final Object impl = originalHibernateProxy.getHibernateLazyInitializer().getImplementation(); final Object impl = originalHibernateProxy.getHibernateLazyInitializer().getImplementation();
// can we return it? // can we return it?
@ -734,7 +736,7 @@ public Object narrowProxy(Object proxy, EntityPersister persister, EntityKey key
// Otherwise, create the narrowed proxy // Otherwise, create the narrowed proxy
final HibernateProxy narrowedProxy = (HibernateProxy) persister.createProxy( key.getIdentifier(), session ); final HibernateProxy narrowedProxy = asHibernateProxy( persister.createProxy( key.getIdentifier(), session ) );
// set the read-only/modifiable mode in the new proxy to what it was in the original 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(); final boolean readOnlyOrig = originalHibernateProxy.getHibernateLazyInitializer().isReadOnly();
@ -744,7 +746,7 @@ public Object narrowProxy(Object proxy, EntityPersister persister, EntityKey key
} }
else { else {
if ( object != null ) { if ( object != null ) {
final LazyInitializer li = ( (HibernateProxy) proxy ).getHibernateLazyInitializer(); final LazyInitializer li = asHibernateProxy( proxy ).getHibernateLazyInitializer();
li.setImplementation( object ); li.setImplementation( object );
} }
return proxy; return proxy;
@ -1316,8 +1318,8 @@ && isFoundInParent( propertyName, childEntity, persister, collectionPersister, p
if ( mergeMap != null ) { if ( mergeMap != null ) {
for ( Object o : mergeMap.entrySet() ) { for ( Object o : mergeMap.entrySet() ) {
final Entry<?,?> mergeMapEntry = (Entry<?,?>) o; final Entry<?,?> mergeMapEntry = (Entry<?,?>) o;
if ( mergeMapEntry.getKey() instanceof HibernateProxy ) { if ( isHibernateProxy( mergeMapEntry.getKey() ) ) {
final HibernateProxy proxy = (HibernateProxy) mergeMapEntry.getKey(); final HibernateProxy proxy = asHibernateProxy( mergeMapEntry.getKey() );
if ( persister.isSubclassEntityName( proxy.getHibernateLazyInitializer().getEntityName() ) ) { if ( persister.isSubclassEntityName( proxy.getHibernateLazyInitializer().getEntityName() ) ) {
boolean found = isFoundInParent( boolean found = isFoundInParent(
propertyName, propertyName,
@ -1480,8 +1482,9 @@ public boolean isReadOnly(Object entityOrProxy) {
throw new AssertionFailure( "object must be non-null." ); throw new AssertionFailure( "object must be non-null." );
} }
boolean isReadOnly; boolean isReadOnly;
if ( entityOrProxy instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( entityOrProxy );
isReadOnly = ( (HibernateProxy) entityOrProxy ).getHibernateLazyInitializer().isReadOnly(); if ( lazyInitializer != null ) {
isReadOnly = lazyInitializer.isReadOnly();
} }
else { else {
final EntityEntry ee = getEntry( entityOrProxy ); final EntityEntry ee = getEntry( entityOrProxy );
@ -1501,8 +1504,8 @@ public void setReadOnly(Object object, boolean readOnly) {
if ( isReadOnly( object ) == readOnly ) { if ( isReadOnly( object ) == readOnly ) {
return; return;
} }
if ( object instanceof HibernateProxy ) { if ( isHibernateProxy( object ) ) {
final HibernateProxy proxy = (HibernateProxy) object; final HibernateProxy proxy = asHibernateProxy( object );
setProxyReadOnly( proxy, readOnly ); setProxyReadOnly( proxy, readOnly );
if ( Hibernate.isInitialized( proxy ) ) { if ( Hibernate.isInitialized( proxy ) ) {
setEntityReadOnly( setEntityReadOnly(
@ -1516,8 +1519,8 @@ public void setReadOnly(Object object, boolean readOnly) {
// PersistenceContext.proxyFor( entity ) returns entity if there is no proxy for that entity // PersistenceContext.proxyFor( entity ) returns entity if there is no proxy for that entity
// so need to check the return value to be sure it is really a proxy // so need to check the return value to be sure it is really a proxy
final Object maybeProxy = getSession().getPersistenceContextInternal().proxyFor( object ); final Object maybeProxy = getSession().getPersistenceContextInternal().proxyFor( object );
if ( maybeProxy instanceof HibernateProxy ) { if ( isHibernateProxy( maybeProxy ) ) {
setProxyReadOnly( (HibernateProxy) maybeProxy, readOnly ); setProxyReadOnly( asHibernateProxy( maybeProxy ), readOnly );
} }
} }
} }
@ -1689,7 +1692,8 @@ public static StatefulPersistenceContext deserialize(
rtn.hasNonReadOnlyEntities = ois.readBoolean(); rtn.hasNonReadOnlyEntities = ois.readBoolean();
int count = ois.readInt(); int count = ois.readInt();
if ( LOG.isTraceEnabled() ) { final boolean traceEnabled = LOG.isTraceEnabled();
if ( traceEnabled ) {
LOG.trace( "Starting deserialization of [" + count + "] entitiesByKey entries" ); LOG.trace( "Starting deserialization of [" + count + "] entitiesByKey entries" );
} }
rtn.entitiesByKey = CollectionHelper.mapOfSize(Math.max(count, INIT_COLL_SIZE)); rtn.entitiesByKey = CollectionHelper.mapOfSize(Math.max(count, INIT_COLL_SIZE));
@ -1698,7 +1702,7 @@ public static StatefulPersistenceContext deserialize(
} }
count = ois.readInt(); count = ois.readInt();
if ( LOG.isTraceEnabled() ) { if ( traceEnabled ) {
LOG.trace( "Starting deserialization of [" + count + "] entitiesByUniqueKey entries" ); LOG.trace( "Starting deserialization of [" + count + "] entitiesByUniqueKey entries" );
} }
if ( count != 0 ) { if ( count != 0 ) {
@ -1709,26 +1713,27 @@ public static StatefulPersistenceContext deserialize(
} }
count = ois.readInt(); count = ois.readInt();
if ( LOG.isTraceEnabled() ) { if ( traceEnabled ) {
LOG.trace( "Starting deserialization of [" + count + "] proxiesByKey entries" ); LOG.trace( "Starting deserialization of [" + count + "] proxiesByKey entries" );
} }
for ( int i = 0; i < count; i++ ) { for ( int i = 0; i < count; i++ ) {
final EntityKey ek = EntityKey.deserialize( ois, sfi ); final EntityKey ek = EntityKey.deserialize( ois, sfi );
final Object proxy = ois.readObject(); final Object proxy = ois.readObject();
if ( proxy instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( proxy );
( (HibernateProxy) proxy ).getHibernateLazyInitializer().setSession( session ); if ( lazyInitializer != null ) {
lazyInitializer.setSession( session );
rtn.getOrInitializeProxiesByKey().put( ek, proxy ); rtn.getOrInitializeProxiesByKey().put( ek, proxy );
} }
else { else {
// otherwise, the proxy was pruned during the serialization process // otherwise, the proxy was pruned during the serialization process
if ( LOG.isTraceEnabled() ) { if ( traceEnabled ) {
LOG.trace( "Encountered pruned proxy" ); LOG.trace( "Encountered pruned proxy" );
} }
} }
} }
count = ois.readInt(); count = ois.readInt();
if ( LOG.isTraceEnabled() ) { if ( traceEnabled ) {
LOG.trace( "Starting deserialization of [" + count + "] entitySnapshotsByKey entries" ); LOG.trace( "Starting deserialization of [" + count + "] entitySnapshotsByKey entries" );
} }
rtn.entitySnapshotsByKey = CollectionHelper.mapOfSize(Math.max(count, INIT_COLL_SIZE)); rtn.entitySnapshotsByKey = CollectionHelper.mapOfSize(Math.max(count, INIT_COLL_SIZE));
@ -1739,7 +1744,7 @@ public static StatefulPersistenceContext deserialize(
rtn.entityEntryContext = EntityEntryContext.deserialize( ois, rtn ); rtn.entityEntryContext = EntityEntryContext.deserialize( ois, rtn );
count = ois.readInt(); count = ois.readInt();
if ( LOG.isTraceEnabled() ) { if ( traceEnabled ) {
LOG.trace( "Starting deserialization of [" + count + "] collectionsByKey entries" ); LOG.trace( "Starting deserialization of [" + count + "] collectionsByKey entries" );
} }
rtn.collectionsByKey = CollectionHelper.mapOfSize(Math.max(count, INIT_COLL_SIZE)); rtn.collectionsByKey = CollectionHelper.mapOfSize(Math.max(count, INIT_COLL_SIZE));
@ -1751,7 +1756,7 @@ public static StatefulPersistenceContext deserialize(
} }
count = ois.readInt(); count = ois.readInt();
if ( LOG.isTraceEnabled() ) { if ( traceEnabled ) {
LOG.trace( "Starting deserialization of [" + count + "] collectionEntries entries" ); LOG.trace( "Starting deserialization of [" + count + "] collectionEntries entries" );
} }
for ( int i = 0; i < count; i++ ) { for ( int i = 0; i < count; i++ ) {
@ -1762,7 +1767,7 @@ public static StatefulPersistenceContext deserialize(
} }
count = ois.readInt(); count = ois.readInt();
if ( LOG.isTraceEnabled() ) { if ( traceEnabled ) {
LOG.trace( "Starting deserialization of [" + count + "] arrayHolders entries" ); LOG.trace( "Starting deserialization of [" + count + "] arrayHolders entries" );
} }
if ( count != 0 ) { if ( count != 0 ) {
@ -1773,7 +1778,7 @@ public static StatefulPersistenceContext deserialize(
} }
count = ois.readInt(); count = ois.readInt();
if ( LOG.isTraceEnabled() ) { if ( traceEnabled ) {
LOG.trace( "Starting deserialization of [" + count + "] nullifiableEntityKey entries" ); LOG.trace( "Starting deserialization of [" + count + "] nullifiableEntityKey entries" );
} }
rtn.nullifiableEntityKeys = new HashSet<>(); rtn.nullifiableEntityKeys = new HashSet<>();

View File

@ -844,10 +844,10 @@ public boolean hasAnyQueuedActions() {
} }
public void unScheduleDeletion(EntityEntry entry, Object rescuedEntity) { public void unScheduleDeletion(EntityEntry entry, Object rescuedEntity) {
if ( rescuedEntity instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( rescuedEntity );
LazyInitializer initializer = ( (HibernateProxy) rescuedEntity ).getHibernateLazyInitializer(); if ( lazyInitializer != null ) {
if ( !initializer.isUninitialized() ) { if ( !lazyInitializer.isUninitialized() ) {
rescuedEntity = initializer.getImplementation( session ); rescuedEntity = lazyInitializer.getImplementation( session );
} }
} }
if ( deletions != null ) { if ( deletions != null ) {

View File

@ -7,6 +7,7 @@
package org.hibernate.engine.spi; package org.hibernate.engine.spi;
import org.hibernate.engine.internal.ManagedTypeHelper; import org.hibernate.engine.internal.ManagedTypeHelper;
import org.hibernate.proxy.HibernateProxy;
/** /**
* For a full explanation of the purpose of this interface * For a full explanation of the purpose of this interface
@ -53,4 +54,8 @@ default CompositeTracker asCompositeTracker() {
return null; return null;
} }
default HibernateProxy asHibernateProxy() {
return null;
}
} }

View File

@ -98,14 +98,13 @@ public void onDelete(DeleteEvent event, DeleteContext transientEntities) throws
private boolean optimizeUnloadedDelete(DeleteEvent event) { private boolean optimizeUnloadedDelete(DeleteEvent event) {
final Object object = event.getObject(); final Object object = event.getObject();
if ( object instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( object );
HibernateProxy proxy = (HibernateProxy) object; if ( lazyInitializer != null ) {
LazyInitializer initializer = proxy.getHibernateLazyInitializer(); if ( lazyInitializer.isUninitialized() ) {
if ( initializer.isUninitialized() ) {
final EventSource source = event.getSession(); final EventSource source = event.getSession();
final EntityPersister persister = source.getFactory().getMappingMetamodel() final EntityPersister persister = source.getFactory().getMappingMetamodel()
.findEntityDescriptor( initializer.getEntityName() ); .findEntityDescriptor( lazyInitializer.getEntityName() );
final Object id = initializer.getIdentifier(); final Object id = lazyInitializer.getIdentifier();
final EntityKey key = source.generateEntityKey( id, persister ); final EntityKey key = source.generateEntityKey( id, persister );
final PersistenceContext persistenceContext = source.getPersistenceContextInternal(); final PersistenceContext persistenceContext = source.getPersistenceContextInternal();
if ( !persistenceContext.containsEntity( key ) if ( !persistenceContext.containsEntity( key )

View File

@ -47,25 +47,25 @@ public void onEvict(EvictEvent event) throws HibernateException {
if ( object == null ) { if ( object == null ) {
throw new NullPointerException( "null passed to Session.evict()" ); throw new NullPointerException( "null passed to Session.evict()" );
} }
if ( object instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( object );
final LazyInitializer li = ( (HibernateProxy) object ).getHibernateLazyInitializer(); if ( lazyInitializer != null ) {
final Object id = li.getInternalIdentifier(); final Object id = lazyInitializer.getInternalIdentifier();
if ( id == null ) { if ( id == null ) {
throw new IllegalArgumentException( "Could not determine identifier of proxy passed to evict()" ); throw new IllegalArgumentException( "Could not determine identifier of proxy passed to evict()" );
} }
final EntityPersister persister = source.getFactory() final EntityPersister persister = source.getFactory()
.getMappingMetamodel() .getMappingMetamodel()
.getEntityDescriptor( li.getEntityName() ); .getEntityDescriptor( lazyInitializer.getEntityName() );
final EntityKey key = source.generateEntityKey( id, persister ); final EntityKey key = source.generateEntityKey( id, persister );
persistenceContext.removeProxy( key ); persistenceContext.removeProxy( key );
if ( !li.isUninitialized() ) { if ( !lazyInitializer.isUninitialized() ) {
final Object entity = persistenceContext.removeEntity( key ); final Object entity = persistenceContext.removeEntity( key );
if ( entity != null ) { if ( entity != null ) {
EntityEntry entry = persistenceContext.removeEntry( entity ); EntityEntry entry = persistenceContext.removeEntry( entity );
doEvict( entity, key, entry.getPersister(), event.getSession() ); doEvict( entity, key, entry.getPersister(), event.getSession() );
} }
} }
li.unsetSession(); lazyInitializer.unsetSession();
} }
else { else {
EntityEntry entry = persistenceContext.getEntry( object ); EntityEntry entry = persistenceContext.getEntry( object );

View File

@ -6,8 +6,6 @@
*/ */
package org.hibernate.event.internal; package org.hibernate.event.internal;
import java.util.List;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.NonUniqueObjectException; import org.hibernate.NonUniqueObjectException;
@ -298,11 +296,8 @@ private static Object loadWithProxyFactory(LoadEvent event, EntityPersister pers
// existing proxy associated with the PC - and if so, use it // existing proxy associated with the PC - and if so, use it
final Object proxy = persistenceContext.getProxy( keyToLoad ); final Object proxy = persistenceContext.getProxy( keyToLoad );
if ( proxy != null ) { if ( proxy != null ) {
if ( LOG.isTraceEnabled() ) { LOG.trace( "Entity proxy found in session cache" );
LOG.trace( "Entity proxy found in session cache" ); if ( LOG.isDebugEnabled() && HibernateProxy.extractLazyInitializer( proxy ).isUnwrap() ) {
}
if ( LOG.isDebugEnabled()
&& ( (HibernateProxy) proxy ).getHibernateLazyInitializer().isUnwrap() ) {
LOG.debug( "Ignoring NO_PROXY to honor laziness" ); LOG.debug( "Ignoring NO_PROXY to honor laziness" );
} }
return persistenceContext.narrowProxy( proxy, persister, keyToLoad, null ); return persistenceContext.narrowProxy( proxy, persister, keyToLoad, null );
@ -378,7 +373,7 @@ private Object narrowedProxy(LoadEvent event, EntityPersister persister, EntityK
if ( LOG.isTraceEnabled() ) { if ( LOG.isTraceEnabled() ) {
LOG.trace( "Entity proxy found in session cache" ); LOG.trace( "Entity proxy found in session cache" );
} }
final LazyInitializer li = ( (HibernateProxy) proxy ).getHibernateLazyInitializer(); LazyInitializer li = HibernateProxy.extractLazyInitializer( proxy );
if ( li.isUnwrap() ) { if ( li.isUnwrap() ) {
return li.getImplementation(); return li.getImplementation();
} }
@ -601,8 +596,9 @@ protected Object loadFromDatasource(final LoadEvent event, final EntityPersister
// persister/loader/initializer sensitive to this fact - possibly // persister/loader/initializer sensitive to this fact - possibly
// passing LoadType along // passing LoadType along
if ( entity instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( entity );
entity = ( (HibernateProxy) entity ).getHibernateLazyInitializer().getImplementation(); if ( lazyInitializer != null ) {
entity = lazyInitializer.getImplementation();
} }
final StatisticsImplementor statistics = event.getSession().getFactory().getStatistics(); final StatisticsImplementor statistics = event.getSession().getFactory().getStatistics();

View File

@ -103,14 +103,14 @@ public void onMerge(MergeEvent event, MergeContext copiedAlready) throws Hiberna
// NOTE : `original` is the value being merged // NOTE : `original` is the value being merged
if ( original != null ) { if ( original != null ) {
final EventSource source = event.getSession(); final EventSource source = event.getSession();
if ( original instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( original );
LazyInitializer li = ( (HibernateProxy) original ).getHibernateLazyInitializer(); if ( lazyInitializer != null ) {
if ( li.isUninitialized() ) { if ( lazyInitializer.isUninitialized() ) {
LOG.trace( "Ignoring uninitialized proxy" ); LOG.trace( "Ignoring uninitialized proxy" );
event.setResult( source.load( li.getEntityName(), li.getInternalIdentifier() ) ); event.setResult( source.load( lazyInitializer.getEntityName(), lazyInitializer.getInternalIdentifier() ) );
} }
else { else {
doMerge( event, copiedAlready, li.getImplementation() ); doMerge( event, copiedAlready, lazyInitializer.getImplementation() );
} }
} }
else if ( isPersistentAttributeInterceptable( original ) ) { else if ( isPersistentAttributeInterceptable( original ) ) {

View File

@ -62,15 +62,15 @@ public void onPersist(PersistEvent event) throws HibernateException {
*/ */
public void onPersist(PersistEvent event, PersistContext createCache) throws HibernateException { public void onPersist(PersistEvent event, PersistContext createCache) throws HibernateException {
final Object object = event.getObject(); final Object object = event.getObject();
if ( object instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( object );
LazyInitializer li = ( (HibernateProxy) object ).getHibernateLazyInitializer(); if ( lazyInitializer != null ) {
if ( li.isUninitialized() ) { if ( lazyInitializer.isUninitialized() ) {
if ( li.getSession() != event.getSession() ) { if ( lazyInitializer.getSession() != event.getSession() ) {
throw new PersistentObjectException( "uninitialized proxy passed to persist()" ); throw new PersistentObjectException( "uninitialized proxy passed to persist()" );
} }
} }
else { else {
persist( event, createCache, li.getImplementation() ); persist( event, createCache, lazyInitializer.getImplementation() );
} }
} }
else { else {

View File

@ -32,6 +32,7 @@
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
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;
/** /**
* Defines the default listener used by Hibernate for handling save-update * Defines the default listener used by Hibernate for handling save-update
@ -57,8 +58,9 @@ public void onSaveOrUpdate(SaveOrUpdateEvent event) {
if ( requestedId != null ) { if ( requestedId != null ) {
//assign the requested id to the proxy, *before* //assign the requested id to the proxy, *before*
//reassociating the proxy //reassociating the proxy
if ( object instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( object );
( (HibernateProxy) object ).getHibernateLazyInitializer().setIdentifier( requestedId ); if ( lazyInitializer != null ) {
lazyInitializer.setIdentifier( requestedId );
} }
} }

View File

@ -697,8 +697,8 @@ public RootGraphImplementor<?> findEntityGraphByName(String name) {
@Override @Override
public String bestGuessEntityName(Object object) { public String bestGuessEntityName(Object object) {
if ( object instanceof HibernateProxy ) { final LazyInitializer initializer = HibernateProxy.extractLazyInitializer( object );
LazyInitializer initializer = ( (HibernateProxy) object ).getHibernateLazyInitializer(); if ( initializer != null ) {
// it is possible for this method to be called during flush processing, // it is possible for this method to be called during flush processing,
// so make certain that we do not accidentally initialize an uninitialized proxy // so make certain that we do not accidentally initialize an uninitialized proxy
if ( initializer.isUninitialized() ) { if ( initializer.isUninitialized() ) {
@ -1081,10 +1081,9 @@ public <T> BindableType<? extends T> resolveParameterBindType(T bindValue) {
} }
Class<?> clazz; Class<?> clazz;
if (bindValue instanceof HibernateProxy) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( bindValue );
HibernateProxy proxy = (HibernateProxy) bindValue; if ( lazyInitializer != null ) {
LazyInitializer li = proxy.getHibernateLazyInitializer(); clazz = lazyInitializer.getPersistentClass();
clazz = li.getPersistentClass();
} }
else { else {
clazz = bindValue.getClass(); clazz = bindValue.getClass();

View File

@ -162,6 +162,7 @@
import static org.hibernate.cfg.AvailableSettings.JPA_LOCK_TIMEOUT; import static org.hibernate.cfg.AvailableSettings.JPA_LOCK_TIMEOUT;
import static org.hibernate.cfg.AvailableSettings.JPA_SHARED_CACHE_RETRIEVE_MODE; import static org.hibernate.cfg.AvailableSettings.JPA_SHARED_CACHE_RETRIEVE_MODE;
import static org.hibernate.cfg.AvailableSettings.JPA_SHARED_CACHE_STORE_MODE; import static org.hibernate.cfg.AvailableSettings.JPA_SHARED_CACHE_STORE_MODE;
import static org.hibernate.engine.internal.ManagedTypeHelper.isHibernateProxy;
import static org.hibernate.jpa.HibernateHints.HINT_READ_ONLY; import static org.hibernate.jpa.HibernateHints.HINT_READ_ONLY;
import static org.hibernate.jpa.LegacySpecHints.HINT_JAVAEE_LOCK_TIMEOUT; import static org.hibernate.jpa.LegacySpecHints.HINT_JAVAEE_LOCK_TIMEOUT;
import static org.hibernate.jpa.LegacySpecHints.HINT_JAVAEE_QUERY_TIMEOUT; import static org.hibernate.jpa.LegacySpecHints.HINT_JAVAEE_QUERY_TIMEOUT;
@ -534,8 +535,9 @@ public LockMode getCurrentLockMode(Object object) throws HibernateException {
throw new NullPointerException( "null object passed to getCurrentLockMode()" ); throw new NullPointerException( "null object passed to getCurrentLockMode()" );
} }
if ( object instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( object );
object = ( (HibernateProxy) object ).getHibernateLazyInitializer().getImplementation( this ); if ( lazyInitializer != null ) {
object = lazyInitializer.getImplementation( this );
if ( object == null ) { if ( object == null ) {
return LockMode.NONE; return LockMode.NONE;
} }
@ -1034,8 +1036,9 @@ public Object immediateLoad(String entityName, Object id) throws HibernateExcept
fireLoadNoChecks( event, LoadEventListener.IMMEDIATE_LOAD ); fireLoadNoChecks( event, LoadEventListener.IMMEDIATE_LOAD );
Object result = event.getResult(); Object result = event.getResult();
finishWithEventInstance( event ); finishWithEventInstance( event );
if ( result instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( result );
return ( (HibernateProxy) result ).getHibernateLazyInitializer().getImplementation(); if ( lazyInitializer != null ) {
return lazyInitializer.getImplementation();
} }
return result; return result;
} }
@ -1496,12 +1499,12 @@ public EntityPersister getEntityPersister(final String entityName, final Object
public Object getIdentifier(Object object) throws HibernateException { public Object getIdentifier(Object object) throws HibernateException {
checkOpen(); checkOpen();
checkTransactionSynchStatus(); checkTransactionSynchStatus();
if ( object instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( object );
LazyInitializer li = ( (HibernateProxy) object ).getHibernateLazyInitializer(); if ( lazyInitializer != null ) {
if ( li.getSession() != this ) { if ( lazyInitializer.getSession() != this ) {
throw new TransientObjectException( "The proxy was not associated with this session" ); throw new TransientObjectException( "The proxy was not associated with this session" );
} }
return li.getInternalIdentifier(); return lazyInitializer.getInternalIdentifier();
} }
else { else {
EntityEntry entry = persistenceContext.getEntry( object ); EntityEntry entry = persistenceContext.getEntry( object );
@ -1529,7 +1532,13 @@ public Object getContextEntityIdentifier(Object object) {
} }
private Object getProxyIdentifier(Object proxy) { private Object getProxyIdentifier(Object proxy) {
return ( (HibernateProxy) proxy ).getHibernateLazyInitializer().getInternalIdentifier(); final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( proxy );
if ( lazyInitializer != null ) {
return lazyInitializer.getInternalIdentifier();
}
else {
throw new HibernateException( "Argument was not an HibernateProxy, which is a requirement for this method" );
}
} }
@Override @Override
@ -1542,23 +1551,23 @@ public boolean contains(Object object) {
} }
try { try {
if ( object instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( object );
if ( lazyInitializer != null ) {
//do not use proxiesByKey, since not all //do not use proxiesByKey, since not all
//proxies that point to this session's //proxies that point to this session's
//instances are in that collection! //instances are in that collection!
LazyInitializer li = ( (HibernateProxy) object ).getHibernateLazyInitializer(); if ( lazyInitializer.isUninitialized() ) {
if ( li.isUninitialized() ) {
//if it is an uninitialized proxy, pointing //if it is an uninitialized proxy, pointing
//with this session, then when it is accessed, //with this session, then when it is accessed,
//the underlying instance will be "contained" //the underlying instance will be "contained"
return li.getSession() == this; return lazyInitializer.getSession() == this;
} }
else { else {
//if it is initialized, see if the underlying //if it is initialized, see if the underlying
//instance is contained, since we need to //instance is contained, since we need to
//account for the fact that it might have been //account for the fact that it might have been
//evicted //evicted
object = li.getImplementation(); object = lazyInitializer.getImplementation();
} }
} }
@ -1569,7 +1578,7 @@ public boolean contains(Object object) {
delayedAfterCompletion(); delayedAfterCompletion();
if ( entry == null ) { if ( entry == null ) {
if ( !(object instanceof HibernateProxy) && persistenceContext.getEntry( object ) == null ) { if ( ! ( isHibernateProxy( object ) ) && persistenceContext.getEntry( object ) == null ) {
// check if it is even an entity -> if not throw an exception (per JPA) // check if it is even an entity -> if not throw an exception (per JPA)
try { try {
final String entityName = getEntityNameResolver().resolveEntityName( object ); final String entityName = getEntityNameResolver().resolveEntityName( object );
@ -1620,11 +1629,11 @@ public boolean contains(String entityName, Object object) {
} }
} }
if ( object instanceof HibernateProxy ) { final LazyInitializer li = HibernateProxy.extractLazyInitializer( object );
if ( li != null ) {
//do not use proxiesByKey, since not all //do not use proxiesByKey, since not all
//proxies that point to this session's //proxies that point to this session's
//instances are in that collection! //instances are in that collection!
LazyInitializer li = ( (HibernateProxy) object ).getHibernateLazyInitializer();
if ( li.isUninitialized() ) { if ( li.isUninitialized() ) {
//if it is an uninitialized proxy, pointing //if it is an uninitialized proxy, pointing
//with this session, then when it is accessed, //with this session, then when it is accessed,
@ -1693,14 +1702,14 @@ public void initializeCollection(PersistentCollection<?> collection, boolean wri
@Override @Override
public String bestGuessEntityName(Object object) { public String bestGuessEntityName(Object object) {
if ( object instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( object );
LazyInitializer initializer = ( (HibernateProxy) object ).getHibernateLazyInitializer(); if ( lazyInitializer != null ) {
// it is possible for this method to be called during flush processing, // it is possible for this method to be called during flush processing,
// so make certain that we do not accidentally initialize an uninitialized proxy // so make certain that we do not accidentally initialize an uninitialized proxy
if ( initializer.isUninitialized() ) { if ( lazyInitializer.isUninitialized() ) {
return initializer.getEntityName(); return lazyInitializer.getEntityName();
} }
object = initializer.getImplementation(); object = lazyInitializer.getImplementation();
} }
EntityEntry entry = persistenceContext.getEntry( object ); EntityEntry entry = persistenceContext.getEntry( object );
if ( entry == null ) { if ( entry == null ) {
@ -1715,11 +1724,12 @@ public String bestGuessEntityName(Object object) {
public String getEntityName(Object object) { public String getEntityName(Object object) {
checkOpen(); checkOpen();
// checkTransactionSynchStatus(); // checkTransactionSynchStatus();
if ( object instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( object );
if ( lazyInitializer != null ) {
if ( !persistenceContext.containsProxy( object ) ) { if ( !persistenceContext.containsProxy( object ) ) {
throw new TransientObjectException( "proxy was not associated with the session" ); throw new TransientObjectException( "proxy was not associated with the session" );
} }
object = ( (HibernateProxy) object ).getHibernateLazyInitializer().getImplementation(); object = lazyInitializer.getImplementation();
} }
EntityEntry entry = persistenceContext.getEntry( object ); EntityEntry entry = persistenceContext.getEntry( object );
@ -1732,9 +1742,9 @@ public String getEntityName(Object object) {
@Override @SuppressWarnings("unchecked") @Override @SuppressWarnings("unchecked")
public <T> T getReference(T object) { public <T> T getReference(T object) {
checkOpen(); checkOpen();
if ( object instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( object );
LazyInitializer initializer = ( (HibernateProxy) object ).getHibernateLazyInitializer(); if ( lazyInitializer != null ) {
return (T) getReference( initializer.getPersistentClass(), initializer.getIdentifier() ); return (T) getReference( lazyInitializer.getPersistentClass(), lazyInitializer.getIdentifier() );
} }
else { else {
EntityPersister persister = getEntityPersister( null, object ); EntityPersister persister = getEntityPersister( null, object );

View File

@ -328,7 +328,7 @@ public Object internalLoad(
if ( LOG.isTraceEnabled() ) { if ( LOG.isTraceEnabled() ) {
LOG.trace( "Entity proxy found in session cache" ); LOG.trace( "Entity proxy found in session cache" );
} }
if ( LOG.isDebugEnabled() && ( (HibernateProxy) proxy ).getHibernateLazyInitializer().isUnwrap() ) { if ( LOG.isDebugEnabled() && HibernateProxy.extractLazyInitializer( proxy ).isUnwrap() ) {
LOG.debug( "Ignoring NO_PROXY to honor laziness" ); LOG.debug( "Ignoring NO_PROXY to honor laziness" );
} }
@ -387,8 +387,7 @@ public void fetch(Object association) {
checkOpen(); checkOpen();
PersistenceContext persistenceContext = getPersistenceContext(); PersistenceContext persistenceContext = getPersistenceContext();
if ( association instanceof HibernateProxy ) { if ( association instanceof HibernateProxy ) {
LazyInitializer initializer = final LazyInitializer initializer = HibernateProxy.extractLazyInitializer( association );
((HibernateProxy) association).getHibernateLazyInitializer();
if ( initializer.isUninitialized() ) { if ( initializer.isUninitialized() ) {
String entityName = initializer.getEntityName(); String entityName = initializer.getEntityName();
Object id = initializer.getIdentifier(); Object id = initializer.getIdentifier();
@ -479,8 +478,9 @@ private void managedFlush() {
@Override @Override
public String bestGuessEntityName(Object object) { public String bestGuessEntityName(Object object) {
if ( object instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( object );
object = ( (HibernateProxy) object ).getHibernateLazyInitializer().getImplementation(); if ( lazyInitializer != null ) {
object = lazyInitializer.getImplementation();
} }
return guessEntityName( object ); return guessEntityName( object );
} }

View File

@ -17,6 +17,7 @@
import org.hibernate.jpa.internal.util.PersistenceUtilHelper; import org.hibernate.jpa.internal.util.PersistenceUtilHelper;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
@ -69,8 +70,9 @@ public Object getIdentifier(Object entity) {
throw new IllegalArgumentException( "Passed entity cannot be null" ); throw new IllegalArgumentException( "Passed entity cannot be null" );
} }
if ( entity instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( entity );
return ((HibernateProxy) entity).getHibernateLazyInitializer().getInternalIdentifier(); if ( lazyInitializer != null ) {
return lazyInitializer.getInternalIdentifier();
} }
else if ( isManagedEntity( entity ) ) { else if ( isManagedEntity( entity ) ) {
EntityEntry entityEntry = asManagedEntity( entity ).$$_hibernate_getEntityEntry(); EntityEntry entityEntry = asManagedEntity( entity ).$$_hibernate_getEntityEntry();

View File

@ -80,8 +80,9 @@ private PersistenceUtilHelper() {
* @return The appropriate LoadState (see above) * @return The appropriate LoadState (see above)
*/ */
public static LoadState isLoaded(Object reference) { public static LoadState isLoaded(Object reference) {
if ( reference instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( reference );
final boolean isInitialized = !( (HibernateProxy) reference ).getHibernateLazyInitializer().isUninitialized(); if ( lazyInitializer != null ) {
final boolean isInitialized = !lazyInitializer.isUninitialized();
return isInitialized ? LoadState.LOADED : LoadState.NOT_LOADED; return isInitialized ? LoadState.LOADED : LoadState.NOT_LOADED;
} }
else if ( isPersistentAttributeInterceptable( reference ) ) { else if ( isPersistentAttributeInterceptable( reference ) ) {
@ -118,15 +119,15 @@ private static BytecodeLazyAttributeInterceptor extractInterceptor(PersistentAtt
*/ */
public static LoadState isLoadedWithoutReference(Object entity, String attributeName, MetadataCache cache) { public static LoadState isLoadedWithoutReference(Object entity, String attributeName, MetadataCache cache) {
boolean sureFromUs = false; boolean sureFromUs = false;
if ( entity instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( entity );
LazyInitializer li = ( (HibernateProxy) entity ).getHibernateLazyInitializer(); if ( lazyInitializer != null ) {
if ( li.isUninitialized() ) { if ( lazyInitializer.isUninitialized() ) {
// we have an uninitialized proxy, the attribute cannot be loaded // we have an uninitialized proxy, the attribute cannot be loaded
return LoadState.NOT_LOADED; return LoadState.NOT_LOADED;
} }
else { else {
// swap the proxy with target (for proper class name resolution) // swap the proxy with target (for proper class name resolution)
entity = li.getImplementation(); entity = lazyInitializer.getImplementation();
} }
sureFromUs = true; sureFromUs = true;
} }
@ -200,15 +201,15 @@ else if ( sureFromUs ) {
* @return The LoadState * @return The LoadState
*/ */
public static LoadState isLoadedWithReference(Object entity, String attributeName, MetadataCache cache) { public static LoadState isLoadedWithReference(Object entity, String attributeName, MetadataCache cache) {
if ( entity instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( entity );
final LazyInitializer li = ( (HibernateProxy) entity ).getHibernateLazyInitializer(); if ( lazyInitializer != null ) {
if ( li.isUninitialized() ) { if ( lazyInitializer.isUninitialized() ) {
// we have an uninitialized proxy, the attribute cannot be loaded // we have an uninitialized proxy, the attribute cannot be loaded
return LoadState.NOT_LOADED; return LoadState.NOT_LOADED;
} }
else { else {
// swap the proxy with target (for proper class name resolution) // swap the proxy with target (for proper class name resolution)
entity = li.getImplementation(); entity = lazyInitializer.getImplementation();
} }
} }

View File

@ -200,8 +200,8 @@ protected final T doLoad(Object normalizedNaturalIdValue) {
if ( loaded != null ) { if ( loaded != null ) {
final EntityEntry entry; final EntityEntry entry;
if ( loaded instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( loaded );
LazyInitializer lazyInitializer = ( (HibernateProxy) loaded ).getHibernateLazyInitializer(); if ( lazyInitializer != null ) {
entry = persistenceContext.getEntry( lazyInitializer.getImplementation() ); entry = persistenceContext.getEntry( lazyInitializer.getImplementation() );
} }
else { else {

View File

@ -31,6 +31,9 @@
import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
import static org.hibernate.engine.internal.ManagedTypeHelper.asHibernateProxy;
import static org.hibernate.engine.internal.ManagedTypeHelper.isHibernateProxy;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
@ -210,8 +213,8 @@ private void initializeIfNecessary(Object result) {
return; return;
} }
if ( result instanceof HibernateProxy ) { if ( isHibernateProxy( result ) ) {
final HibernateProxy hibernateProxy = (HibernateProxy) result; final HibernateProxy hibernateProxy = asHibernateProxy( result );
final LazyInitializer initializer = hibernateProxy.getHibernateLazyInitializer(); final LazyInitializer initializer = hibernateProxy.getHibernateLazyInitializer();
if ( initializer.isUninitialized() ) { if ( initializer.isUninitialized() ) {
initializer.initialize(); initializer.initialize();

View File

@ -431,7 +431,7 @@ private Object convertCacheEntryToEntity(
if ( proxy != null ) { if ( proxy != null ) {
// there is already a proxy for this impl // there is already a proxy for this impl
// only set the status to read-only if the proxy is read-only // only set the status to read-only if the proxy is read-only
isReadOnly = ( (HibernateProxy) proxy ).getHibernateLazyInitializer().isReadOnly(); isReadOnly = HibernateProxy.extractLazyInitializer( proxy ).isReadOnly();
} }
else { else {
isReadOnly = source.isDefaultReadOnly(); isReadOnly = source.isDefaultReadOnly();

View File

@ -28,6 +28,7 @@
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.property.access.spi.PropertyAccess; import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import org.hibernate.spi.NavigablePath; import org.hibernate.spi.NavigablePath;
import org.hibernate.sql.ast.Clause; import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.spi.SqlAstCreationState; import org.hibernate.sql.ast.spi.SqlAstCreationState;
@ -144,16 +145,18 @@ public IdentifierValue getUnsavedStrategy() {
@Override @Override
public Object getIdentifier(Object entity, SharedSessionContractImplementor session) { public Object getIdentifier(Object entity, SharedSessionContractImplementor session) {
if ( entity instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( entity );
return ( (HibernateProxy) entity ).getHibernateLazyInitializer().getIdentifier(); if ( lazyInitializer != null ) {
return lazyInitializer.getIdentifier();
} }
return propertyAccess.getGetter().get( entity ); return propertyAccess.getGetter().get( entity );
} }
@Override @Override
public Object getIdentifier(Object entity) { public Object getIdentifier(Object entity) {
if ( entity instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( entity );
return ( (HibernateProxy) entity ).getHibernateLazyInitializer().getIdentifier(); if ( lazyInitializer != null ) {
return lazyInitializer.getIdentifier();
} }
return propertyAccess.getGetter().get( entity ); return propertyAccess.getGetter().get( entity );
} }

View File

@ -15,6 +15,7 @@
import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.property.access.spi.PropertyAccess; import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import org.hibernate.spi.NavigablePath; import org.hibernate.spi.NavigablePath;
import org.hibernate.sql.ast.Clause; import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.spi.SqlSelection; import org.hibernate.sql.ast.spi.SqlSelection;
@ -85,16 +86,18 @@ public void applySqlSelections(
@Override @Override
public Object getIdentifier(Object entity, SharedSessionContractImplementor session) { public Object getIdentifier(Object entity, SharedSessionContractImplementor session) {
if ( entity instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( entity );
return ( (HibernateProxy) entity ).getHibernateLazyInitializer().getIdentifier(); if ( lazyInitializer != null ) {
return lazyInitializer.getIdentifier();
} }
return propertyAccess.getGetter().get( entity ); return propertyAccess.getGetter().get( entity );
} }
@Override @Override
public Object getIdentifier(Object entity) { public Object getIdentifier(Object entity) {
if ( entity instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( entity );
return ( (HibernateProxy) entity ).getHibernateLazyInitializer().getIdentifier(); if ( lazyInitializer != null ) {
return lazyInitializer.getIdentifier();
} }
return propertyAccess.getGetter().get( entity ); return propertyAccess.getGetter().get( entity );
} }

View File

@ -31,6 +31,7 @@
import org.hibernate.metamodel.model.domain.NavigableRole; import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.property.access.spi.PropertyAccess; import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import org.hibernate.query.sqm.ComparisonOperator; import org.hibernate.query.sqm.ComparisonOperator;
import org.hibernate.spi.NavigablePath; import org.hibernate.spi.NavigablePath;
import org.hibernate.sql.ast.Clause; import org.hibernate.sql.ast.Clause;
@ -429,8 +430,11 @@ public Object getAssociationKeyFromSide(
if ( targetObject == null ) { if ( targetObject == null ) {
return null; return null;
} }
if ( refersToPrimaryKey && targetObject instanceof HibernateProxy ) { if ( refersToPrimaryKey ) {
return ( (HibernateProxy) targetObject ).getHibernateLazyInitializer().getIdentifier(); final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( targetObject );
if ( lazyInitializer != null ) {
return lazyInitializer.getIdentifier();
}
} }
final ModelPart modelPart = side.getModelPart(); final ModelPart modelPart = side.getModelPart();
if ( modelPart instanceof EntityIdentifierMapping ) { if ( modelPart instanceof EntityIdentifierMapping ) {

View File

@ -15,6 +15,7 @@
import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.property.access.internal.AbstractFieldSerialForm; import org.hibernate.property.access.internal.AbstractFieldSerialForm;
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
/** /**
* Field-based implementation of Setter * Field-based implementation of Setter
@ -68,8 +69,9 @@ public void set(Object target, Object value) {
} }
else { else {
final String valueType; final String valueType;
if ( value instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( value );
valueType = ( (HibernateProxy) value ).getHibernateLazyInitializer().getEntityName(); if ( lazyInitializer != null ) {
valueType = lazyInitializer.getEntityName();
} }
else { else {
valueType = value.getClass().getTypeName(); valueType = value.getClass().getTypeName();

View File

@ -7,12 +7,33 @@
package org.hibernate.proxy; package org.hibernate.proxy;
import java.io.Serializable; import java.io.Serializable;
import org.hibernate.engine.spi.PrimeAmongSecondarySupertypes;
/** /**
* Marker interface for entity proxies * Marker interface for entity proxies
* *
* @author Gavin King * @author Gavin King
*/ */
public interface HibernateProxy extends Serializable { public interface HibernateProxy extends Serializable, PrimeAmongSecondarySupertypes {
/**
* Extract the LazyInitializer from the object, if
* and only if the object is actually an HibernateProxy.
* If not, null is returned.
* @param object any entity
* @return either null (if object is not an HibernateProxy) or the LazyInitializer of the HibernateProxy.
*/
static LazyInitializer extractLazyInitializer(final Object object) {
if ( object instanceof PrimeAmongSecondarySupertypes ) {
PrimeAmongSecondarySupertypes t = (PrimeAmongSecondarySupertypes) object;
final HibernateProxy hibernateProxy = t.asHibernateProxy();
if ( hibernateProxy != null ) {
return hibernateProxy.getHibernateLazyInitializer();
}
}
return null;
}
/** /**
* Perform serialization-time write-replacement of this proxy. * Perform serialization-time write-replacement of this proxy.
* *
@ -26,4 +47,14 @@ public interface HibernateProxy extends Serializable {
* @return The lazy initializer. * @return The lazy initializer.
*/ */
LazyInitializer getHibernateLazyInitializer(); LazyInitializer getHibernateLazyInitializer();
/**
* Special internal contract to optimize type checking
* @see PrimeAmongSecondarySupertypes
* @return this same instance
*/
@Override
default HibernateProxy asHibernateProxy() {
return this;
}
} }

View File

@ -13,6 +13,7 @@
import java.util.Set; import java.util.Set;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.engine.spi.PrimeAmongSecondarySupertypes;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.ReflectHelper;
@ -105,7 +106,12 @@ private HibernateProxy getHibernateProxy()
public HibernateProxy run() { public HibernateProxy run() {
try { try {
return (HibernateProxy) proxyClass.getConstructor().newInstance(); PrimeAmongSecondarySupertypes instance = (PrimeAmongSecondarySupertypes) proxyClass.getConstructor().newInstance();
final HibernateProxy hibernateProxy = instance.asHibernateProxy();
if ( hibernateProxy == null ) {
throw new HibernateException( "Produced proxy does not correctly implement HibernateProxy" );
}
return hibernateProxy;
} }
catch (NoSuchMethodException e) { catch (NoSuchMethodException e) {
String logMessage = LOG.bytecodeEnhancementFailedBecauseOfDefaultConstructor( entityName ); String logMessage = LOG.bytecodeEnhancementFailedBecauseOfDefaultConstructor( entityName );

View File

@ -6,6 +6,10 @@
*/ */
package org.hibernate.proxy.pojo.bytebuddy; package org.hibernate.proxy.pojo.bytebuddy;
import static net.bytebuddy.matcher.ElementMatchers.anyOf;
import static net.bytebuddy.matcher.ElementMatchers.isDeclaredBy;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static org.hibernate.engine.internal.ManagedTypeHelper.asHibernateProxy;
import static org.hibernate.internal.CoreLogging.messageLogger; import static org.hibernate.internal.CoreLogging.messageLogger;
import java.io.Serializable; import java.io.Serializable;
@ -19,6 +23,15 @@
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.bytecode.internal.bytebuddy.ByteBuddyState; import org.hibernate.bytecode.internal.bytebuddy.ByteBuddyState;
import org.hibernate.engine.spi.CompositeOwner;
import org.hibernate.engine.spi.CompositeTracker;
import org.hibernate.engine.spi.Managed;
import org.hibernate.engine.spi.ManagedComposite;
import org.hibernate.engine.spi.ManagedEntity;
import org.hibernate.engine.spi.ManagedMappedSuperclass;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.engine.spi.PrimeAmongSecondarySupertypes;
import org.hibernate.engine.spi.SelfDirtinessTracker;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
@ -33,6 +46,7 @@
import net.bytebuddy.description.type.TypeList; import net.bytebuddy.description.type.TypeList;
import net.bytebuddy.dynamic.DynamicType; import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy; import net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy;
import net.bytebuddy.implementation.DefaultMethodCall;
import net.bytebuddy.implementation.SuperMethodCall; import net.bytebuddy.implementation.SuperMethodCall;
import net.bytebuddy.pool.TypePool; import net.bytebuddy.pool.TypePool;
@ -92,7 +106,25 @@ private Function<ByteBuddy, DynamicType.Builder<?>> proxyBuilder(TypeDefinition
.intercept( SuperMethodCall.INSTANCE ) .intercept( SuperMethodCall.INSTANCE )
.defineField( ProxyConfiguration.INTERCEPTOR_FIELD_NAME, ProxyConfiguration.Interceptor.class, Visibility.PRIVATE ) .defineField( ProxyConfiguration.INTERCEPTOR_FIELD_NAME, ProxyConfiguration.Interceptor.class, Visibility.PRIVATE )
.implement( ProxyConfiguration.class ) .implement( ProxyConfiguration.class )
.intercept( helpers.getInterceptorFieldAccessor() ); .intercept( helpers.getInterceptorFieldAccessor() )
.ignoreAlso( isDeclaredBy( ManagedEntity.class ).and( named( "asManagedEntity" ) ) )
.ignoreAlso( isDeclaredBy( PrimeAmongSecondarySupertypes.class ).and( named( "asManagedEntity" ) ) )
.ignoreAlso( isDeclaredBy( PersistentAttributeInterceptable.class ).and( named( "asPersistentAttributeInterceptable" ) ) )
.ignoreAlso( isDeclaredBy( PrimeAmongSecondarySupertypes.class ).and( named( "asPersistentAttributeInterceptable" ) ) )
.ignoreAlso( isDeclaredBy( SelfDirtinessTracker.class ).and( named( "asSelfDirtinessTracker" ) ) )
.ignoreAlso( isDeclaredBy( PrimeAmongSecondarySupertypes.class ).and( named( "asSelfDirtinessTracker" ) ) )
.ignoreAlso( isDeclaredBy( Managed.class ).and( named( "asManaged" ) ) )
.ignoreAlso( isDeclaredBy( PrimeAmongSecondarySupertypes.class ).and( named( "asManaged" ) ) )
.ignoreAlso( isDeclaredBy( ManagedComposite.class ).and( named( "asManagedComposite" ) ) )
.ignoreAlso( isDeclaredBy( PrimeAmongSecondarySupertypes.class ).and( named( "asManagedComposite" ) ) )
.ignoreAlso( isDeclaredBy( ManagedMappedSuperclass.class ).and( named( "asManagedMappedSuperclass" ) ) )
.ignoreAlso( isDeclaredBy( PrimeAmongSecondarySupertypes.class ).and( named( "asManagedMappedSuperclass" ) ) )
.ignoreAlso( isDeclaredBy( CompositeOwner.class ).and( named( "asCompositeOwner" ) ) )
.ignoreAlso( isDeclaredBy( PrimeAmongSecondarySupertypes.class ).and( named( "asCompositeOwner" ) ) )
.ignoreAlso( isDeclaredBy( CompositeTracker.class ).and( named( "asCompositeTracker" ) ) )
.ignoreAlso( isDeclaredBy( PrimeAmongSecondarySupertypes.class ).and( named( "asCompositeTracker" ) ) )
.ignoreAlso( isDeclaredBy( HibernateProxy.class ).and( named( "asHibernateProxy" ) ) )
.ignoreAlso( isDeclaredBy( PrimeAmongSecondarySupertypes.class ).and( named( "asHibernateProxy" ) ) );
} }
public HibernateProxy deserializeProxy(SerializableProxy serializableProxy) { public HibernateProxy deserializeProxy(SerializableProxy serializableProxy) {
@ -114,7 +146,7 @@ public HibernateProxy deserializeProxy(SerializableProxy serializableProxy) {
serializableProxy.getPersistentClass(), serializableProxy.getPersistentClass(),
serializableProxy.getInterfaces() serializableProxy.getInterfaces()
); );
final HibernateProxy proxy = (HibernateProxy) proxyClass.newInstance(); final HibernateProxy proxy = asHibernateProxy( proxyClass.newInstance() );
( (ProxyConfiguration) proxy ).$$_hibernate_set_interceptor( interceptor ); ( (ProxyConfiguration) proxy ).$$_hibernate_set_interceptor( interceptor );
return proxy; return proxy;
} }

View File

@ -24,6 +24,7 @@
import org.hibernate.metamodel.spi.ValueAccess; import org.hibernate.metamodel.spi.ValueAccess;
import org.hibernate.property.access.spi.PropertyAccess; import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import org.hibernate.spi.NavigablePath; import org.hibernate.spi.NavigablePath;
import org.hibernate.sql.results.graph.AbstractFetchParentAccess; import org.hibernate.sql.results.graph.AbstractFetchParentAccess;
import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.AssemblerCreationState;
@ -196,7 +197,8 @@ public void initializeInstance(RowProcessingState processingState) {
if ( compositeInstance != NULL_MARKER ) { if ( compositeInstance != NULL_MARKER ) {
notifyResolutionListeners( compositeInstance ); notifyResolutionListeners( compositeInstance );
if ( compositeInstance instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( compositeInstance );
if ( lazyInitializer != null ) {
final Initializer parentInitializer = processingState.resolveInitializer( navigablePath.getParent() ); final Initializer parentInitializer = processingState.resolveInitializer( navigablePath.getParent() );
if ( parentInitializer != this ) { if ( parentInitializer != this ) {
( (FetchParentAccess) parentInitializer ).registerResolutionListener( (entity) -> { ( (FetchParentAccess) parentInitializer ).registerResolutionListener( (entity) -> {
@ -215,7 +217,7 @@ public void initializeInstance(RowProcessingState processingState) {
.getInstantiator() .getInstantiator()
.instantiate( this, sessionFactory); .instantiate( this, sessionFactory);
stateInjected = true; stateInjected = true;
( (HibernateProxy) compositeInstance ).getHibernateLazyInitializer().setImplementation( target ); lazyInitializer.setImplementation( target );
} }
} }
else if ( stateAllNull == FALSE && stateInjected != TRUE ) { else if ( stateAllNull == FALSE && stateInjected != TRUE ) {

View File

@ -648,9 +648,8 @@ public void initializeInstance(RowProcessingState rowProcessingState) {
final SharedSessionContractImplementor session = rowProcessingState.getJdbcValuesSourceProcessingState().getSession(); final SharedSessionContractImplementor session = rowProcessingState.getJdbcValuesSourceProcessingState().getSession();
final PersistenceContext persistenceContext = session.getPersistenceContext(); final PersistenceContext persistenceContext = session.getPersistenceContext();
if ( entityInstance instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( entityInstance );
LazyInitializer hibernateLazyInitializer = ( (HibernateProxy) entityInstance ).getHibernateLazyInitializer(); if ( lazyInitializer != null ) {
Object instance = persistenceContext.getEntity( entityKey ); Object instance = persistenceContext.getEntity( entityKey );
if ( instance == null ) { if ( instance == null ) {
instance = resolveInstance( instance = resolveInstance(
@ -662,7 +661,7 @@ public void initializeInstance(RowProcessingState rowProcessingState) {
initializeEntity( instance, rowProcessingState, session, persistenceContext ); initializeEntity( instance, rowProcessingState, session, persistenceContext );
} }
hibernateLazyInitializer.setImplementation( instance ); lazyInitializer.setImplementation( instance );
entityInstanceForNotify = instance; entityInstanceForNotify = instance;
} }
else { else {
@ -865,10 +864,11 @@ private void initializeEntity(
isReallyReadOnly = true; isReallyReadOnly = true;
} }
else { else {
if ( entityInstance instanceof HibernateProxy) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( entityInstance );
if ( lazyInitializer != null ) {
// there is already a proxy for this impl // there is already a proxy for this impl
// only set the status to read-only if the proxy is read-only // only set the status to read-only if the proxy is read-only
isReallyReadOnly = ( (HibernateProxy) entityInstance ).getHibernateLazyInitializer().isReadOnly(); isReallyReadOnly = lazyInitializer.isReadOnly();
} }
} }
if ( isReallyReadOnly ) { if ( isReallyReadOnly ) {

View File

@ -19,6 +19,7 @@
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.UniqueKeyLoadable; import org.hibernate.persister.entity.UniqueKeyLoadable;
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import org.hibernate.spi.NavigablePath; import org.hibernate.spi.NavigablePath;
import org.hibernate.sql.results.graph.AbstractFetchParentAccess; import org.hibernate.sql.results.graph.AbstractFetchParentAccess;
import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.DomainResultAssembler;
@ -168,9 +169,9 @@ && isEnhancedForLazyLoading( parentAccess ) ) {
); );
} }
if ( entityInstance instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( entityInstance );
( (HibernateProxy) entityInstance ).getHibernateLazyInitializer() if ( lazyInitializer != null ) {
.setUnwrap( referencedModelPart.isUnwrapProxy() && concreteDescriptor.isInstrumented() ); lazyInitializer.setUnwrap( referencedModelPart.isUnwrapProxy() && concreteDescriptor.isInstrumented() );
} }
} }
} }

View File

@ -20,6 +20,7 @@
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import org.hibernate.spi.NavigablePath; import org.hibernate.spi.NavigablePath;
import org.hibernate.spi.EntityIdentifierNavigablePath; import org.hibernate.spi.EntityIdentifierNavigablePath;
import org.hibernate.sql.results.graph.AbstractFetchParentAccess; import org.hibernate.sql.results.graph.AbstractFetchParentAccess;
@ -216,8 +217,9 @@ public void initializeInstance(RowProcessingState rowProcessingState) {
} }
final boolean unwrapProxy = toOneMapping.isUnwrapProxy() && isEnhancedForLazyLoading; final boolean unwrapProxy = toOneMapping.isUnwrapProxy() && isEnhancedForLazyLoading;
if ( entityInstance instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( entityInstance );
( (HibernateProxy) entityInstance ).getHibernateLazyInitializer().setUnwrap( unwrapProxy ); if ( lazyInitializer != null ) {
lazyInitializer.setUnwrap( unwrapProxy );
} }
isInitialized = true; isInitialized = true;
} }

View File

@ -28,6 +28,7 @@
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.UniqueKeyLoadable; import org.hibernate.persister.entity.UniqueKeyLoadable;
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import org.hibernate.spi.NavigablePath; import org.hibernate.spi.NavigablePath;
import org.hibernate.sql.ast.Clause; import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.spi.SqlSelection; import org.hibernate.sql.ast.spi.SqlSelection;
@ -275,12 +276,13 @@ public Object assemble(RowProcessingState rowProcessingState, JdbcValuesSourcePr
initializer.resolveInstance( rowProcessingState ); initializer.resolveInstance( rowProcessingState );
} }
final Object initializedInstance = initializer.getInitializedInstance(); final Object initializedInstance = initializer.getInitializedInstance();
if ( initializedInstance instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( initializedInstance );
if ( lazyInitializer != null ) {
if ( initializedInstance.getClass().isAssignableFrom( javaType.getJavaTypeClass() ) ) { if ( initializedInstance.getClass().isAssignableFrom( javaType.getJavaTypeClass() ) ) {
return initializedInstance; return initializedInstance;
} }
initializer.initializeInstance( rowProcessingState ); initializer.initializeInstance( rowProcessingState );
return ( (HibernateProxy) initializedInstance ).getHibernateLazyInitializer().getImplementation(); return lazyInitializer.getImplementation();
} }
return initializedInstance; return initializedInstance;
} }

View File

@ -155,12 +155,12 @@ private EntityPersister guessEntityPersister(Object object) {
// this code is largely copied from Session's bestGuessEntityName // this code is largely copied from Session's bestGuessEntityName
Object entity = object; Object entity = object;
if ( entity instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( entity );
final LazyInitializer initializer = ( (HibernateProxy) entity ).getHibernateLazyInitializer(); if ( lazyInitializer != null ) {
if ( initializer.isUninitialized() ) { if ( lazyInitializer.isUninitialized() ) {
entityName = initializer.getEntityName(); entityName = lazyInitializer.getEntityName();
} }
entity = initializer.getImplementation(); entity = lazyInitializer.getImplementation();
} }
if ( entityName == null ) { if ( entityName == null ) {

View File

@ -91,8 +91,8 @@ public boolean contains(Object collection, Object childObject, SharedSessionCont
while ( elems.hasNext() ) { while ( elems.hasNext() ) {
Object element = elems.next(); Object element = elems.next();
// worrying about proxies is perhaps a little bit of overkill here... // worrying about proxies is perhaps a little bit of overkill here...
if ( element instanceof HibernateProxy ) { final LazyInitializer li = HibernateProxy.extractLazyInitializer( element );
LazyInitializer li = ( (HibernateProxy) element ).getHibernateLazyInitializer(); if ( li != null ) {
if ( !li.isUninitialized() ) { if ( !li.isUninitialized() ) {
element = li.getImplementation(); element = li.getImplementation();
} }

View File

@ -24,8 +24,12 @@
import org.hibernate.persister.entity.Joinable; import org.hibernate.persister.entity.Joinable;
import org.hibernate.persister.entity.UniqueKeyLoadable; import org.hibernate.persister.entity.UniqueKeyLoadable;
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
import static org.hibernate.engine.internal.ManagedTypeHelper.asHibernateProxy;
import static org.hibernate.engine.internal.ManagedTypeHelper.isHibernateProxy;
/** /**
* Base for types which map associations to persistent entities. * Base for types which map associations to persistent entities.
* *
@ -320,8 +324,9 @@ public int getHashCode(Object x, SessionFactoryImplementor factory) {
} }
final Object id; final Object id;
if ( x instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( x );
id = ( (HibernateProxy) x ).getHibernateLazyInitializer().getInternalIdentifier(); if ( lazyInitializer != null ) {
id = lazyInitializer.getInternalIdentifier();
} }
else { else {
final Class<?> mappedClass = persister.getMappedClass(); final Class<?> mappedClass = persister.getMappedClass();
@ -349,9 +354,9 @@ public boolean isEqual(Object x, Object y, SessionFactoryImplementor factory) {
final Class<?> mappedClass = persister.getMappedClass(); final Class<?> mappedClass = persister.getMappedClass();
Object xid; Object xid;
if ( x instanceof HibernateProxy ) { final LazyInitializer lazyInitializerX = HibernateProxy.extractLazyInitializer( x );
xid = ( (HibernateProxy) x ).getHibernateLazyInitializer() if ( lazyInitializerX != null ) {
.getInternalIdentifier(); xid = lazyInitializerX.getInternalIdentifier();
} }
else { else {
if ( mappedClass.isAssignableFrom( x.getClass() ) ) { if ( mappedClass.isAssignableFrom( x.getClass() ) ) {
@ -364,9 +369,9 @@ public boolean isEqual(Object x, Object y, SessionFactoryImplementor factory) {
} }
Object yid; Object yid;
if ( y instanceof HibernateProxy ) { final LazyInitializer lazyInitializerY = HibernateProxy.extractLazyInitializer( y );
yid = ( (HibernateProxy) y ).getHibernateLazyInitializer() if ( lazyInitializerY != null ) {
.getInternalIdentifier(); yid = lazyInitializerY.getInternalIdentifier();
} }
else { else {
if ( mappedClass.isAssignableFrom( y.getClass() ) ) { if ( mappedClass.isAssignableFrom( y.getClass() ) ) {
@ -505,8 +510,8 @@ public String toLoggableString(Object value, SessionFactoryImplementor factory)
if ( persister.hasIdentifierProperty() ) { if ( persister.hasIdentifierProperty() ) {
final Object id; final Object id;
if ( value instanceof HibernateProxy ) { if ( isHibernateProxy( value ) ) {
HibernateProxy proxy = (HibernateProxy) value; HibernateProxy proxy = asHibernateProxy( value );
id = proxy.getHibernateLazyInitializer().getInternalIdentifier(); id = proxy.getHibernateLazyInitializer().getInternalIdentifier();
} }
else { else {
@ -652,9 +657,9 @@ protected final Object resolveIdentifier(Object id, SharedSessionContractImpleme
isNullable() isNullable()
); );
if ( proxyOrEntity instanceof HibernateProxy ) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( proxyOrEntity );
( (HibernateProxy) proxyOrEntity ).getHibernateLazyInitializer() if ( lazyInitializer != null ) {
.setUnwrap( isProxyUnwrapEnabled ); lazyInitializer.setUnwrap( isProxyUnwrapEnabled );
} }
return proxyOrEntity; return proxyOrEntity;

View File

@ -0,0 +1,117 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.bytecode.internal.bytebuddy;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Stream;
import org.hibernate.LazyInitializationException;
import org.hibernate.engine.spi.PrimeAmongSecondarySupertypes;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.ProxyFactory;
import org.hibernate.proxy.pojo.bytebuddy.ByteBuddyProxyFactory;
import org.hibernate.proxy.pojo.bytebuddy.ByteBuddyProxyHelper;
import org.hibernate.testing.TestForIssue;
import org.junit.Assert;
import org.junit.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
/**
* Verifies that proxies being generated by ByteBuddyProxyHelper
* do not break the contract with PrimeAmongSecondarySupertypes.
* A problem in this are could obviously manifest as a semantic
* issue, but could also manifest solely as a performance issue;
* therefore we check implementation details via unit tests
* rather than the typical integration test we'd have in such cases.
*
* @author Sanne Grinovero
*/
@TestForIssue( jiraKey = "HHH-15790" )
public class SuperTypesEnhancementTest {
private static final ByteBuddyProxyHelper helper = new ByteBuddyProxyHelper( new ByteBuddyState() );
private static Stream<Arguments> superTypeMethods() {
return Arrays.stream( PrimeAmongSecondarySupertypes.class.getDeclaredMethods() ).map( e -> Arguments.of( e ) );
}
private static Stream<Arguments> interfaces() {
return Arrays.stream( PrimeAmongSecondarySupertypes.class.getDeclaredMethods() ).map( m -> m.getReturnType() ).map( e -> Arguments.of( e ) );
}
@ParameterizedTest
@MethodSource("superTypeMethods")
public void testNamingConventions(Method m) {
final Class<?> returnType = m.getReturnType();
final String expectedMethodName = "as" + returnType.getSimpleName();
Assert.assertEquals( expectedMethodName, m.getName() );
Assert.assertNotNull( m.isDefault() );
}
@ParameterizedTest
@MethodSource("superTypeMethods")
public void testSubInterfaceOverrides(Method m) throws NoSuchMethodException {
final Class<?> returnType = m.getReturnType();
final Method subMethod = returnType.getMethod( m.getName(), m.getParameterTypes() );
Assert.assertNotNull( subMethod );
Assert.assertNotNull( subMethod.isDefault() );
}
@ParameterizedTest
@MethodSource("interfaces")
public void testAllProxyGeneration(Class<?> secondarySuper) {
ProxyFactory enhancer = createProxyFactory( SampleClass.class, secondarySuper );
final Object proxy = enhancer.getProxy( Integer.valueOf( 1 ), null );
Assert.assertTrue( secondarySuper.isAssignableFrom( proxy.getClass() ) );
PrimeAmongSecondarySupertypes casted = (PrimeAmongSecondarySupertypes) proxy;
testForLIE( (SampleClass) proxy );
}
@Test
public void testGeneratedHibernateProxy() {
ProxyFactory enhancer = createProxyFactory( SampleClass.class, HibernateProxy.class );
final Object proxy = enhancer.getProxy( Integer.valueOf( 1 ), null );
Assert.assertTrue( HibernateProxy.class.isAssignableFrom( proxy.getClass() ) );
Assert.assertTrue( proxy instanceof HibernateProxy );
PrimeAmongSecondarySupertypes casted = (PrimeAmongSecondarySupertypes) proxy;
final HibernateProxy extracted = casted.asHibernateProxy();
Assert.assertNotNull( extracted );
Assert.assertSame( proxy, extracted );
testForLIE( (SampleClass) proxy );
}
/**
* Self-check: verify that this is in fact a lazy proxy
*/
private void testForLIE(SampleClass sampleProxy) {
SampleClass other = new SampleClass();
Assert.assertEquals( 7, other.additionMethod( 3,4 ) );
Assert.assertThrows( LazyInitializationException.class, () -> sampleProxy.additionMethod( 3, 4 ) );
}
private ProxyFactory createProxyFactory(Class<?> persistentClass, Class<?>... interfaces) {
ByteBuddyProxyFactory proxyFactory = new ByteBuddyProxyFactory( helper );
proxyFactory.postInstantiate( "", persistentClass, Set.of( interfaces ), null, null, null );
return proxyFactory;
}
//Just a class with some fields and methods to proxy
static class SampleClass {
int intField;
String stringField;
public int additionMethod(int a, int b) {
return a + b;
}
}
}

View File

@ -20,6 +20,9 @@
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
import static org.hibernate.engine.internal.ManagedTypeHelper.asHibernateProxy;
import static org.hibernate.engine.internal.ManagedTypeHelper.isHibernateProxy;
/** /**
* Base class for all Envers event listeners * Base class for all Envers event listeners
* *
@ -92,8 +95,8 @@ private void addCollectionChangeWorkUnit(
String toEntityName; String toEntityName;
Object id; Object id;
if ( value instanceof HibernateProxy ) { if ( isHibernateProxy( value ) ) {
final HibernateProxy hibernateProxy = (HibernateProxy) value; final HibernateProxy hibernateProxy = asHibernateProxy( value );
id = hibernateProxy.getHibernateLazyInitializer().getInternalIdentifier(); id = hibernateProxy.getHibernateLazyInitializer().getInternalIdentifier();
// We've got to initialize the object from the proxy to later read its state. // We've got to initialize the object from the proxy to later read its state.
value = EntityTools.getTargetFromProxy( session.getFactory(), hibernateProxy ); value = EntityTools.getTargetFromProxy( session.getFactory(), hibernateProxy );

View File

@ -19,6 +19,9 @@
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer; import org.hibernate.proxy.LazyInitializer;
import static org.hibernate.engine.internal.ManagedTypeHelper.asHibernateProxy;
import static org.hibernate.engine.internal.ManagedTypeHelper.isHibernateProxy;
/** /**
* @author Adam Warski (adam at warski dot org) * @author Adam Warski (adam at warski dot org)
* @author Hern&aacute;n Chanfreau * @author Hern&aacute;n Chanfreau
@ -105,8 +108,8 @@ private void replaceNonAuditIdProxies(Map versionsEntity, Number revision) {
final Map originalId = (Map) versionsEntity.get( enversService.getConfig().getOriginalIdPropertyName() ); final Map originalId = (Map) versionsEntity.get( enversService.getConfig().getOriginalIdPropertyName() );
for ( Object key : originalId.keySet() ) { for ( Object key : originalId.keySet() ) {
final Object value = originalId.get( key ); final Object value = originalId.get( key );
if ( value instanceof HibernateProxy ) { if ( isHibernateProxy( value ) ) {
final HibernateProxy hibernateProxy = (HibernateProxy) value; final HibernateProxy hibernateProxy = asHibernateProxy( value );
final LazyInitializer initializer = hibernateProxy.getHibernateLazyInitializer(); final LazyInitializer initializer = hibernateProxy.getHibernateLazyInitializer();
final String entityName = initializer.getEntityName(); final String entityName = initializer.getEntityName();
final Object entityId = initializer.getInternalIdentifier(); final Object entityId = initializer.getInternalIdentifier();

View File

@ -15,6 +15,9 @@
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;
import static org.hibernate.engine.internal.ManagedTypeHelper.asHibernateProxy;
import static org.hibernate.engine.internal.ManagedTypeHelper.isHibernateProxy;
/** /**
* An implementation of an identifier mapper for a single basic attribute property. * An implementation of an identifier mapper for a single basic attribute property.
* *
@ -77,8 +80,8 @@ public Object mapToIdFromEntity(final Object data) {
return null; return null;
} }
if ( data instanceof HibernateProxy ) { if ( isHibernateProxy( data ) ) {
final HibernateProxy hibernateProxy = (HibernateProxy) data; final HibernateProxy hibernateProxy = asHibernateProxy( data );
return hibernateProxy.getHibernateLazyInitializer().getInternalIdentifier(); return hibernateProxy.getHibernateLazyInitializer().getInternalIdentifier();
} }
else { else {
@ -99,8 +102,8 @@ public void mapToMapFromEntity(Map<String, Object> data, final Object obj) {
data.put( propertyData.getName(), null ); data.put( propertyData.getName(), null );
} }
else { else {
if ( obj instanceof HibernateProxy ) { if ( isHibernateProxy( obj ) ) {
final HibernateProxy hibernateProxy = (HibernateProxy) obj; final HibernateProxy hibernateProxy = asHibernateProxy( obj );
data.put( propertyData.getName(), hibernateProxy.getHibernateLazyInitializer().getInternalIdentifier() ); data.put( propertyData.getName(), hibernateProxy.getHibernateLazyInitializer().getInternalIdentifier() );
} }
else { else {

View File

@ -20,6 +20,9 @@
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.EntityType; import org.hibernate.type.EntityType;
import static org.hibernate.engine.internal.ManagedTypeHelper.asHibernateProxy;
import static org.hibernate.engine.internal.ManagedTypeHelper.isHibernateProxy;
/** /**
* An extension to the {@link SingleIdMapper} implementation that supports the use case of an {@code @IdClass} * An extension to the {@link SingleIdMapper} implementation that supports the use case of an {@code @IdClass}
* mapping that contains an entity association where the {@code @IdClass} stores the primary key of the * mapping that contains an entity association where the {@code @IdClass} stores the primary key of the
@ -130,8 +133,8 @@ public void mapToMapFromEntity(Map<String, Object> data, Object obj) {
data.put( propertyData.getName(), null ); data.put( propertyData.getName(), null );
} }
else { else {
if ( obj instanceof HibernateProxy ) { if ( isHibernateProxy( obj ) ) {
final HibernateProxy proxy = (HibernateProxy) obj; final HibernateProxy proxy = asHibernateProxy( obj );
data.put( propertyData.getName(), proxy.getHibernateLazyInitializer().getInternalIdentifier() ); data.put( propertyData.getName(), proxy.getHibernateLazyInitializer().getInternalIdentifier() );
} }
else { else {

View File

@ -15,6 +15,9 @@
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
import static org.hibernate.engine.internal.ManagedTypeHelper.asHibernateProxy;
import static org.hibernate.engine.internal.ManagedTypeHelper.isHibernateProxy;
/** /**
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
*/ */
@ -31,8 +34,8 @@ public static Object getIdentifier(SessionImplementor session, String entityName
return null; return null;
} }
if ( obj instanceof HibernateProxy ) { if ( isHibernateProxy( obj ) ) {
final HibernateProxy hibernateProxy = (HibernateProxy) obj; final HibernateProxy hibernateProxy = asHibernateProxy( obj );
return hibernateProxy.getHibernateLazyInitializer().getInternalIdentifier(); return hibernateProxy.getHibernateLazyInitializer().getInternalIdentifier();
} }

View File

@ -20,6 +20,9 @@
import org.hibernate.proxy.LazyInitializer; import org.hibernate.proxy.LazyInitializer;
import org.junit.Test; import org.junit.Test;
import static org.hibernate.engine.internal.ManagedTypeHelper.asHibernateProxy;
import static org.hibernate.engine.internal.ManagedTypeHelper.isHibernateProxy;
/** /**
* @author Tomasz Bech * @author Tomasz Bech
*/ */
@ -114,10 +117,9 @@ public void testRevisionsCounts() {
} }
static Class<?> getClassWithoutInitializingProxy(Object object) { static Class<?> getClassWithoutInitializingProxy(Object object) {
if (object instanceof HibernateProxy) { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( object );
HibernateProxy proxy = (HibernateProxy) object; if ( lazyInitializer != null ) {
LazyInitializer li = proxy.getHibernateLazyInitializer(); return lazyInitializer.getPersistentClass();
return li.getPersistentClass();
} }
else { else {
return object.getClass(); return object.getClass();