HHH-13607 - Exception thrown while flushing uninitialized enhanced proxy with immutable natural ID

(cherry picked from commit 7ceaf3aaa4)
This commit is contained in:
Steve Ebersole 2019-09-04 16:42:10 -05:00 committed by gbadner
parent c3286a2b56
commit 5274f15ef5
1 changed files with 16 additions and 3 deletions

View File

@ -17,10 +17,13 @@ import org.hibernate.StaleObjectStateException;
import org.hibernate.action.internal.DelayedPostInsertIdentifier; import org.hibernate.action.internal.DelayedPostInsertIdentifier;
import org.hibernate.action.internal.EntityUpdateAction; import org.hibernate.action.internal.EntityUpdateAction;
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer; import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor;
import org.hibernate.engine.internal.Nullability; import org.hibernate.engine.internal.Nullability;
import org.hibernate.engine.internal.Versioning; import org.hibernate.engine.internal.Versioning;
import org.hibernate.engine.spi.EntityEntry; import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.EntityKey; import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
import org.hibernate.engine.spi.SelfDirtinessTracker; import org.hibernate.engine.spi.SelfDirtinessTracker;
import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.Status; import org.hibernate.engine.spi.Status;
@ -82,14 +85,24 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
private void checkNaturalId( private void checkNaturalId(
EntityPersister persister, EntityPersister persister,
Object entity,
EntityEntry entry, EntityEntry entry,
Object[] current, Object[] current,
Object[] loaded, Object[] loaded,
SessionImplementor session) { SessionImplementor session) {
if ( entity instanceof PersistentAttributeInterceptable ) {
final PersistentAttributeInterceptor interceptor = ( (PersistentAttributeInterceptable) entity ).$$_hibernate_getInterceptor();
if ( interceptor instanceof EnhancementAsProxyLazinessInterceptor ) {
// EARLY EXIT!!!
// nothing to check - the entity is an un-initialized enhancement-as-proxy reference
return;
}
}
if ( persister.hasNaturalIdentifier() && entry.getStatus() != Status.READ_ONLY ) { if ( persister.hasNaturalIdentifier() && entry.getStatus() != Status.READ_ONLY ) {
if ( !persister.getEntityMetamodel().hasImmutableNaturalId() ) { if ( !persister.getEntityMetamodel().hasImmutableNaturalId() ) {
// SHORT-CUT: if the natural id is mutable (!immutable), no need to do the below checks
// EARLY EXIT!!! // EARLY EXIT!!!
// the natural id is mutable (!immutable), no need to do the below checks
return; return;
} }
@ -112,7 +125,7 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
if ( !propertyType.isEqual( current[naturalIdentifierPropertyIndex], snapshot[i] ) ) { if ( !propertyType.isEqual( current[naturalIdentifierPropertyIndex], snapshot[i] ) ) {
throw new HibernateException( throw new HibernateException(
String.format( String.format(
"An immutable natural identifier of entity %s was altered from %s to %s", "An immutable natural identifier of entity %s was altered from `%s` to `%s`",
persister.getEntityName(), persister.getEntityName(),
propertyTypes[naturalIdentifierPropertyIndex].toLoggableString( propertyTypes[naturalIdentifierPropertyIndex].toLoggableString(
snapshot[i], snapshot[i],
@ -188,7 +201,7 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
// grab its current state // grab its current state
values = persister.getPropertyValues( entity ); values = persister.getPropertyValues( entity );
checkNaturalId( persister, entry, values, loadedState, session ); checkNaturalId( persister, entity, entry, values, loadedState, session );
} }
return values; return values;
} }