HHH-14608 Merge causes StackOverflow when JPA proxy compliance is enabled

(cherry picked from commit 8b02aaf5a8)
This commit is contained in:
Andrea Boriero 2021-05-16 09:35:06 +02:00 committed by gbadner
parent 4783ef11f0
commit 8c66c83ef0
19 changed files with 52 additions and 34 deletions

View File

@ -614,7 +614,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
private void reassociateProxy(LazyInitializer li, HibernateProxy proxy) {
if ( li.getSession() != this.getSession() ) {
final EntityPersister persister = session.getFactory().getMetamodel().entityPersister( li.getEntityName() );
final EntityKey key = session.generateEntityKey( li.getIdentifier(), persister );
final EntityKey key = session.generateEntityKey( li.getInternalIdentifier(), persister );
// any earlier proxy takes precedence
proxiesByKey.putIfAbsent( key, proxy );
proxy.getHibernateLazyInitializer().setSession( session );
@ -1254,7 +1254,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
);
}
if ( found ) {
return proxy.getHibernateLazyInitializer().getIdentifier();
return proxy.getHibernateLazyInitializer().getInternalIdentifier();
}
}
}

View File

@ -54,7 +54,7 @@ public class DefaultEvictEventListener implements EvictEventListener {
if ( object instanceof HibernateProxy ) {
final LazyInitializer li = ( (HibernateProxy) object ).getHibernateLazyInitializer();
final Serializable id = li.getIdentifier();
final Serializable id = li.getInternalIdentifier();
if ( id == null ) {
throw new IllegalArgumentException( "Could not determine identifier of proxy passed to evict()" );
}

View File

@ -120,7 +120,7 @@ public class DefaultMergeEventListener extends AbstractSaveEventListener impleme
LazyInitializer li = ( (HibernateProxy) original ).getHibernateLazyInitializer();
if ( li.isUninitialized() ) {
LOG.trace( "Ignoring uninitialized proxy" );
event.setResult( source.load( li.getEntityName(), li.getIdentifier() ) );
event.setResult( source.load( li.getEntityName(), li.getInternalIdentifier() ) );
//EARLY EXIT!
return;
}

View File

@ -1739,7 +1739,7 @@ public final class SessionImpl
if ( li.getSession() != this ) {
throw new TransientObjectException( "The proxy was not associated with this session" );
}
return li.getIdentifier();
return li.getInternalIdentifier();
}
else {
EntityEntry entry = persistenceContext.getEntry( object );
@ -1767,7 +1767,7 @@ public final class SessionImpl
}
private Serializable getProxyIdentifier(Object proxy) {
return ( (HibernateProxy) proxy ).getHibernateLazyInitializer().getIdentifier();
return ( (HibernateProxy) proxy ).getHibernateLazyInitializer().getInternalIdentifier();
}
private FilterQueryPlan getFilterQueryPlan(

View File

@ -68,7 +68,7 @@ public class PersistenceUnitUtilImpl implements PersistenceUnitUtil, Serializabl
}
if ( entity instanceof HibernateProxy ) {
return ((HibernateProxy) entity).getHibernateLazyInitializer().getIdentifier();
return ((HibernateProxy) entity).getHibernateLazyInitializer().getInternalIdentifier();
}
else if ( entity instanceof ManagedEntity ) {
EntityEntry entityEntry = ((ManagedEntity) entity).$$_hibernate_getEntityEntry();

View File

@ -15,6 +15,7 @@ import org.hibernate.SessionException;
import org.hibernate.TransientObjectException;
import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.CoreLogging;
@ -83,6 +84,11 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
return entityName;
}
@Override
public final Serializable getInternalIdentifier() {
return id;
}
@Override
public final Serializable getIdentifier() {
if ( isUninitialized() && isInitializeProxyWhenAccessingIdentifier() ) {
@ -92,7 +98,7 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
}
private boolean isInitializeProxyWhenAccessingIdentifier() {
return session != null && session.getFactory()
return getSession() != null && getSession().getFactory()
.getSessionFactoryOptions()
.getJpaCompliance().isJpaProxyComplianceEnabled();
}
@ -252,7 +258,7 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
public final void initializeWithoutLoadIfPossible() {
if ( !initialized && session != null && session.isOpen() ) {
final EntityKey key = session.generateEntityKey(
getIdentifier(),
getInternalIdentifier(),
session.getFactory().getMetamodel().entityPersister( getEntityName() )
);
final Object entity = session.getPersistenceContext().getEntity( key );
@ -297,7 +303,7 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
}
private Object getProxyOrNull() {
final EntityKey entityKey = generateEntityKeyOrNull( getIdentifier(), session, getEntityName() );
final EntityKey entityKey = generateEntityKeyOrNull( getInternalIdentifier(), session, getEntityName() );
if ( entityKey != null && session != null && session.isOpen() ) {
return session.getPersistenceContext().getProxy( entityKey );
}
@ -318,8 +324,8 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
@Override
public final Object getImplementation(SharedSessionContractImplementor s) throws HibernateException {
final EntityKey entityKey = generateEntityKeyOrNull( getIdentifier(), s, getEntityName() );
return (entityKey == null ? null : s.getPersistenceContext().getEntity( entityKey ));
final EntityKey entityKey = generateEntityKeyOrNull( getInternalIdentifier(), s, getEntityName() );
return ( entityKey == null ? null : s.getPersistenceContext().getEntity( entityKey ) );
}
/**
@ -368,9 +374,10 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
}
this.readOnly = readOnly;
if ( initialized ) {
EntityKey key = generateEntityKeyOrNull( getIdentifier(), session, getEntityName() );
if ( key != null && session.getPersistenceContext().containsEntity( key ) ) {
session.getPersistenceContext().setReadOnly( target, readOnly );
EntityKey key = generateEntityKeyOrNull( getInternalIdentifier(), session, getEntityName() );
final PersistenceContext persistenceContext = session.getPersistenceContext();
if ( key != null && persistenceContext.containsEntity( key ) ) {
persistenceContext.setReadOnly( target, readOnly );
}
}
}

View File

@ -30,6 +30,17 @@ public interface LazyInitializer {
*
* @return The identifier value.
*/
default Serializable getInternalIdentifier() {
return getIdentifier();
}
/**
* Retrieve the identifier value for the entity our owning proxy represents.
*
* When JPA proxy compliance is enabled the proxy is initialized.
*
* @return The identifier value.
*/
Serializable getIdentifier();
/**

View File

@ -116,7 +116,7 @@ public class MapProxy implements HibernateProxy, Map, Serializable {
private Object serializableProxy() {
return new SerializableMapProxy(
li.getEntityName(),
li.getIdentifier(),
li.getInternalIdentifier(),
( li.isReadOnlySettingAvailable() ? Boolean.valueOf( li.isReadOnly() ) : li.isReadOnlyBeforeAttachedToSession() ),
li.getSessionFactoryUuid(),
li.isAllowLoadOutsideTransaction()

View File

@ -85,7 +85,7 @@ public class ByteBuddyInterceptor extends BasicLazyInitializer implements ProxyC
getEntityName(),
persistentClass,
interfaces,
getIdentifier(),
getInternalIdentifier(),
( isReadOnlySettingAvailable() ? Boolean.valueOf( isReadOnly() ) : isReadOnlyBeforeAttachedToSession() ),
getSessionFactoryUuid(),
isAllowLoadOutsideTransaction(),

View File

@ -123,7 +123,7 @@ public class JavassistLazyInitializer extends BasicLazyInitializer implements Me
getEntityName(),
persistentClass,
interfaces,
getIdentifier(),
getInternalIdentifier(),
( isReadOnlySettingAvailable() ? Boolean.valueOf( isReadOnly() ) : isReadOnlyBeforeAttachedToSession() ),
getSessionFactoryUuid(),
isAllowLoadOutsideTransaction(),

View File

@ -208,7 +208,7 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
id = entity;
}
else if ( HibernateProxy.class.isInstance( entity ) ) {
id = ( (HibernateProxy) entity ).getHibernateLazyInitializer().getIdentifier();
id = ( (HibernateProxy) entity ).getHibernateLazyInitializer().getInternalIdentifier();
}
else {
if ( idGetter == null ) {
@ -432,7 +432,7 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
if ( HibernateProxy.class.isInstance( entity ) ) {
// entity is a proxy, so we know it is not transient; just return ID from proxy
return ( (HibernateProxy) entity ).getHibernateLazyInitializer().getIdentifier();
return ( (HibernateProxy) entity ).getHibernateLazyInitializer().getInternalIdentifier();
}
if ( session != null ) {

View File

@ -369,7 +369,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
final Serializable id;
if ( x instanceof HibernateProxy ) {
id = ( (HibernateProxy) x ).getHibernateLazyInitializer().getIdentifier();
id = ( (HibernateProxy) x ).getHibernateLazyInitializer().getInternalIdentifier();
}
else {
final Class mappedClass = persister.getMappedClass();
@ -399,7 +399,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
Serializable xid;
if ( x instanceof HibernateProxy ) {
xid = ( (HibernateProxy) x ).getHibernateLazyInitializer()
.getIdentifier();
.getInternalIdentifier();
}
else {
if ( mappedClass.isAssignableFrom( x.getClass() ) ) {
@ -414,7 +414,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
Serializable yid;
if ( y instanceof HibernateProxy ) {
yid = ( (HibernateProxy) y ).getHibernateLazyInitializer()
.getIdentifier();
.getInternalIdentifier();
}
else {
if ( mappedClass.isAssignableFrom( y.getClass() ) ) {
@ -546,7 +546,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
final Serializable id;
if ( value instanceof HibernateProxy ) {
HibernateProxy proxy = (HibernateProxy) value;
id = proxy.getHibernateLazyInitializer().getIdentifier();
id = proxy.getHibernateLazyInitializer().getInternalIdentifier();
}
else {
id = persister.getIdentifier( value );

View File

@ -94,7 +94,7 @@ public abstract class BaseEnversEventListener implements EnversListener {
if ( value instanceof HibernateProxy ) {
final HibernateProxy hibernateProxy = (HibernateProxy) value;
id = hibernateProxy.getHibernateLazyInitializer().getIdentifier();
id = hibernateProxy.getHibernateLazyInitializer().getInternalIdentifier();
// We've got to initialize the object from the proxy to later read its state.
value = EntityTools.getTargetFromProxy( session.getFactory(), hibernateProxy );
// HHH-7249

View File

@ -111,7 +111,7 @@ public class EntityInstantiator {
final HibernateProxy hibernateProxy = (HibernateProxy) value;
final LazyInitializer initializer = hibernateProxy.getHibernateLazyInitializer();
final String entityName = initializer.getEntityName();
final Serializable entityId = initializer.getIdentifier();
final Serializable entityId = initializer.getInternalIdentifier();
if ( enversService.getEntitiesConfigurations().isVersioned( entityName ) ) {
final String entityClassName = enversService.getEntitiesConfigurations().get( entityName ).getEntityClassName();
final Class entityClass = ReflectionTools.loadClass(

View File

@ -88,7 +88,7 @@ public class SingleIdMapper extends AbstractIdMapper implements SimpleIdMapperBu
if ( data instanceof HibernateProxy ) {
final HibernateProxy hibernateProxy = (HibernateProxy) data;
return hibernateProxy.getHibernateLazyInitializer().getIdentifier();
return hibernateProxy.getHibernateLazyInitializer().getInternalIdentifier();
}
else {
return AccessController.doPrivileged(
@ -122,7 +122,7 @@ public class SingleIdMapper extends AbstractIdMapper implements SimpleIdMapperBu
else {
if ( obj instanceof HibernateProxy ) {
final HibernateProxy hibernateProxy = (HibernateProxy) obj;
data.put( propertyData.getName(), hibernateProxy.getHibernateLazyInitializer().getIdentifier() );
data.put( propertyData.getName(), hibernateProxy.getHibernateLazyInitializer().getInternalIdentifier() );
}
else {
final Object value = AccessController.doPrivileged(

View File

@ -113,7 +113,7 @@ public class VirtualEntitySingleIdMapper extends SingleIdMapper {
else {
if ( obj instanceof HibernateProxy ) {
final HibernateProxy proxy = (HibernateProxy) obj;
data.put( propertyData.getName(), proxy.getHibernateLazyInitializer().getIdentifier() );
data.put( propertyData.getName(), proxy.getHibernateLazyInitializer().getInternalIdentifier() );
}
else {
final Object value = AccessController.doPrivileged(

View File

@ -33,7 +33,7 @@ public abstract class EntityTools {
if ( obj instanceof HibernateProxy ) {
final HibernateProxy hibernateProxy = (HibernateProxy) obj;
return hibernateProxy.getHibernateLazyInitializer().getIdentifier();
return hibernateProxy.getHibernateLazyInitializer().getInternalIdentifier();
}
return session.getEntityPersister( entityName, obj ).getIdentifier( obj, session );
@ -51,7 +51,7 @@ public abstract class EntityTools {
try {
return tempSession.get(
proxy.getHibernateLazyInitializer().getEntityName(),
proxy.getHibernateLazyInitializer().getIdentifier()
proxy.getHibernateLazyInitializer().getInternalIdentifier()
);
}
finally {

View File

@ -80,7 +80,7 @@ public class RevisionsOfEntityQuery extends AbstractAuditQuery {
Object revisionInfoObject = ( (Map) versionsEntity.get( originalId ) ).get( revisionPropertyName );
if ( revisionInfoObject instanceof HibernateProxy ) {
return (Number) ( (HibernateProxy) revisionInfoObject ).getHibernateLazyInitializer().getIdentifier();
return (Number) ( (HibernateProxy) revisionInfoObject ).getHibernateLazyInitializer().getInternalIdentifier();
}
else {
// Not a proxy - must be read from cache or with a join

View File

@ -114,8 +114,8 @@ public class ProxyIdentifier extends BaseEnversJPAFunctionalTestCase {
LazyInitializer lazyInitializer = proxyCreateByEnvers.getHibernateLazyInitializer();
Assert.assertTrue( lazyInitializer.isUninitialized() );
Assert.assertNotNull( lazyInitializer.getIdentifier() );
Assert.assertEquals( tnae1.getId(), lazyInitializer.getIdentifier() );
Assert.assertNotNull( lazyInitializer.getInternalIdentifier() );
Assert.assertEquals( tnae1.getId(), lazyInitializer.getInternalIdentifier() );
Assert.assertTrue( lazyInitializer.isUninitialized() );
Assert.assertEquals( uste1.getId(), rev1.getReference().getId() );