diff --git a/hibernate-core/src/main/java/org/hibernate/engine/internal/EntityEntryImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/internal/EntityEntryImpl.java index d742a1bfffd1..2362f6b5f6ea 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/internal/EntityEntryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/internal/EntityEntryImpl.java @@ -204,7 +204,7 @@ public void setStatus(Status status) { loadedState = null; } - final Status currentStatus = this.getStatus(); + final Status currentStatus = getStatus(); if ( currentStatus != status ) { setCompressedValue( PREVIOUS_STATUS, currentStatus ); setCompressedValue( STATUS, status ); @@ -264,10 +264,10 @@ public EntityPersister getPersister() { @Override public EntityKey getEntityKey() { if ( cachedEntityKey == null ) { - if ( getId() == null ) { + if ( id == null ) { throw new IllegalStateException( "cannot generate an EntityKey when id is null."); } - cachedEntityKey = new EntityKey( getId(), getPersister() ); + cachedEntityKey = new EntityKey( id, persister ); } return cachedEntityKey; } @@ -306,6 +306,12 @@ public void postUpdate(Object entity, Object[] updatedState, Object nextVersion) .resetDirty( entity, persister, (SessionImplementor) session ); } + @Override + public void postLoad(Object entity) { + processIfSelfDirtinessTracker( entity, EntityEntryImpl::clearDirtyAttributes ); + processIfManagedEntity( entity, EntityEntryImpl::useTracker ); + } + private static void clearDirtyAttributes(final SelfDirtinessTracker entity) { entity.$$_hibernate_clearDirtyAttributes(); } @@ -335,7 +341,8 @@ else if ( earlyInsert ) { return !isExistsInDatabase(); } else { - return session.getPersistenceContextInternal().containsNullifiableEntityKey( this::getEntityKey ); + return session.getPersistenceContextInternal() + .containsNullifiableEntityKey( this::getEntityKey ); } } @@ -344,8 +351,10 @@ public Object getLoadedValue(String propertyName) { if ( loadedState == null || propertyName == null ) { return null; } - final int index = propertyIndex( propertyName ); - return index < 0 ? null : loadedState[index]; + else { + final int index = propertyIndex( propertyName ); + return index < 0 ? null : loadedState[index]; + } } private int propertyIndex(String propertyName) { @@ -359,7 +368,6 @@ public void overwriteLoadedStateCollectionValue(String propertyName, PersistentC if ( getStatus() != READ_ONLY ) { assert propertyName != null; assert loadedState != null; - loadedState[ propertyIndex( propertyName ) ] = collection; } } @@ -389,8 +397,8 @@ private boolean isNonDirtyViaCustomStrategy(Object entity) { final SessionImplementor session = (SessionImplementor) getPersistenceContext().getSession(); final CustomEntityDirtinessStrategy customEntityDirtinessStrategy = session.getFactory().getCustomEntityDirtinessStrategy(); - return customEntityDirtinessStrategy.canDirtyCheck( entity, getPersister(), session ) - && !customEntityDirtinessStrategy.isDirty( entity, getPersister(), session ); + return customEntityDirtinessStrategy.canDirtyCheck( entity, persister, session ) + && !customEntityDirtinessStrategy.isDirty( entity, persister, session ); } private boolean isNonDirtyViaTracker(Object entity) { @@ -431,9 +439,10 @@ public boolean isModifiableEntity() { @Override public void forceLocked(Object entity, Object nextVersion) { version = nextVersion; - loadedState[ persister.getVersionProperty() ] = version; + final int versionProperty = persister.getVersionProperty(); + loadedState[versionProperty] = version; setLockMode( PESSIMISTIC_FORCE_INCREMENT ); - persister.setValue( entity, getPersister().getVersionProperty(), nextVersion ); + persister.setValue( entity, versionProperty, nextVersion ); } @Override @@ -491,7 +500,7 @@ public void setMaybeLazySet(@Nullable ImmutableBitSet maybeLazySet) { @Override public String toString() { return "EntityEntry" - + infoString( getPersister().getEntityName(), id ) + + infoString( persister.getEntityName(), id ) + '(' + getStatus() + ')'; } @@ -559,7 +568,7 @@ public T getExtraState(Class extraStateType if ( next == null ) { return null; } - if ( extraStateType.isAssignableFrom( next.getClass() ) ) { + else if ( extraStateType.isAssignableFrom( next.getClass() ) ) { return (T) next; } else { diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/EntityEntry.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/EntityEntry.java index 19705ede77b6..fbd27332f059 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/EntityEntry.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/EntityEntry.java @@ -70,6 +70,8 @@ public interface EntityEntry { Object getRowId(); + void postLoad(Object entity); + /** * Handle updating the internal state of the entry after actually performing * the database update. Specifically, we update the snapshot information and diff --git a/hibernate-core/src/main/java/org/hibernate/loader/internal/CacheLoadHelper.java b/hibernate-core/src/main/java/org/hibernate/loader/internal/CacheLoadHelper.java index d7530ebe7fa6..5fb197135030 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/internal/CacheLoadHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/internal/CacheLoadHelper.java @@ -334,21 +334,23 @@ private static Object convertCacheEntryToEntity( ); } final Object version = getVersion( values, subclassPersister ); + final EntityEntry entityEntry = persistenceContext.addEntry( + entity, + isReadOnly ? Status.READ_ONLY : Status.MANAGED, + values, + null, + entityId, + version, + LockMode.NONE, + true, + subclassPersister, + false + ); holder.setEntityEntry( - persistenceContext.addEntry( - entity, - isReadOnly ? Status.READ_ONLY : Status.MANAGED, - values, - null, - entityId, - version, - LockMode.NONE, - true, - subclassPersister, - false - ) + entityEntry ); subclassPersister.afterInitialize( entity, source ); + entityEntry.postLoad( entity ); persistenceContext.initializeNonLazyCollections(); return entity; diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java index 9ca947fd2226..56e2a0f91ad6 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java @@ -57,12 +57,10 @@ import org.hibernate.engine.spi.EntityHolder; import org.hibernate.engine.spi.EntityKey; import org.hibernate.engine.spi.LoadQueryInfluencers; -import org.hibernate.engine.spi.ManagedEntity; import org.hibernate.engine.spi.NaturalIdResolutions; import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.PersistentAttributeInterceptable; import org.hibernate.engine.spi.PersistentAttributeInterceptor; -import org.hibernate.engine.spi.SelfDirtinessTracker; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; @@ -283,9 +281,7 @@ import static org.hibernate.boot.model.internal.SoftDeleteHelper.resolveSoftDeleteMapping; import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable; import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable; -import static org.hibernate.engine.internal.ManagedTypeHelper.processIfManagedEntity; import static org.hibernate.engine.internal.ManagedTypeHelper.processIfPersistentAttributeInterceptable; -import static org.hibernate.engine.internal.ManagedTypeHelper.processIfSelfDirtinessTracker; import static org.hibernate.generator.EventType.INSERT; import static org.hibernate.generator.EventType.UPDATE; import static org.hibernate.internal.util.ReflectHelper.isAbstractClass; @@ -4042,38 +4038,36 @@ public boolean isVersionPropertyGenerated() { && ( isVersionGeneratedOnExecution() || isVersionGeneratedBeforeExecution() ); } + private Generator versionPropertyGenerator() { + return getEntityMetamodel().getGenerators()[ getVersionProperty() ]; + } + public boolean isVersionGeneratedOnExecution() { - final Generator strategy = getEntityMetamodel().getGenerators()[ getVersionProperty() ]; - return strategy != null && strategy.generatesSometimes() && strategy.generatedOnExecution(); + final Generator strategy = versionPropertyGenerator(); + return strategy != null + && strategy.generatesSometimes() + && strategy.generatedOnExecution(); } public boolean isVersionGeneratedBeforeExecution() { - final Generator strategy = getEntityMetamodel().getGenerators()[ getVersionProperty() ]; - return strategy != null && strategy.generatesSometimes() && !strategy.generatedOnExecution(); + final Generator strategy = versionPropertyGenerator(); + return strategy != null + && strategy.generatesSometimes() + && !strategy.generatedOnExecution(); } @Override public void afterInitialize(Object entity, SharedSessionContractImplementor session) { - if ( isPersistentAttributeInterceptable( entity ) && getRepresentationStrategy().getMode() == POJO ) { - final BytecodeLazyAttributeInterceptor interceptor = getEntityMetamodel().getBytecodeEnhancementMetadata() - .extractLazyInterceptor( entity ); + if ( isPersistentAttributeInterceptable( entity ) + && getRepresentationStrategy().getMode() == POJO ) { + final BytecodeLazyAttributeInterceptor interceptor = + getEntityMetamodel().getBytecodeEnhancementMetadata() + .extractLazyInterceptor( entity ); assert interceptor != null; if ( interceptor.getLinkedSession() == null ) { interceptor.setSession( session ); } } - - // clear the fields that are marked as dirty in the dirtiness tracker - processIfSelfDirtinessTracker( entity, AbstractEntityPersister::clearDirtyAttributes ); - processIfManagedEntity( entity, AbstractEntityPersister::useTracker ); - } - - private static void clearDirtyAttributes(final SelfDirtinessTracker entity) { - entity.$$_hibernate_clearDirtyAttributes(); - } - - private static void useTracker(final ManagedEntity entity) { - entity.$$_hibernate_setUseTracker( true ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityInitializerImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityInitializerImpl.java index f08316e43636..09e5bc0c5ed2 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityInitializerImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityInitializerImpl.java @@ -1403,6 +1403,7 @@ protected void initializeEntityInstance(EntityInitializerData data) { takeSnapshot( data, session, persistenceContext, entityEntry, resolvedEntityState ); data.concreteDescriptor.afterInitialize( entityInstanceForNotify, session ); + entityEntry.postLoad( entityInstanceForNotify ); assert data.concreteDescriptor.getIdentifier( entityInstanceForNotify, session ) != null;