HHH-11147 - Allow enhanced entities to be returned in a completely uninitialized state

(cherry picked from commit 94c49aaaa6)
This commit is contained in:
Steve Ebersole 2019-06-14 08:22:07 -05:00
parent 6d2c4aad29
commit 0a17f5ba6d
3 changed files with 34 additions and 19 deletions

View File

@ -6,11 +6,13 @@
*/
package org.hibernate.bytecode.enhance.spi.interceptor;
import java.io.Serializable;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.bytecode.BytecodeLogger;
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
@ -22,6 +24,7 @@ import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.tuple.entity.EntityTuplizer;
import org.hibernate.type.CompositeType;
import org.hibernate.type.Type;
/**
* @author Steve Ebersole
@ -213,16 +216,29 @@ public class EnhancementAsProxyLazinessInterceptor extends AbstractLazyLoadInter
}
if ( identifierAttributeNames.contains( attributeName ) ) {
EnhancementHelper.performWork(
this,
(session, isTempSession) -> session.getFactory()
.getMetamodel()
.entityPersister( getEntityName() )
.getEntityTuplizer()
.getPropertyValue( target, attributeName ),
getEntityName(),
attributeName
);
// it is illegal for the identifier value to be changed. Normally Hibernate
// validates this during flush. However, here it is dangerous to just allow the
// new value to be set and continue on waiting for the flush for validation
// because this interceptor manages the entity's entry in the PC itself. So
// just do the check here up-front
final boolean changed;
if ( nonAggregatedCidMapper == null ) {
changed = ! entityKey.getPersister().getIdentifierType().isEqual( oldValue, newValue );
}
else {
final int subAttrIndex = nonAggregatedCidMapper.getPropertyIndex( attributeName );
final Type subAttrType = nonAggregatedCidMapper.getSubtypes()[subAttrIndex];
changed = ! subAttrType.isEqual( oldValue, newValue );
}
if ( changed ) {
throw new HibernateException(
"identifier of an instance of " + entityKey.getEntityName() + " was altered from " + oldValue + " to " + newValue
);
}
// otherwise, setId has been called but passing in the same value - just pass it through
return newValue;
}
if ( ! inLineDirtyChecking ) {

View File

@ -74,6 +74,10 @@ public final class EntityKey implements Serializable {
return persister.getEntityName();
}
public EntityPersister getPersister() {
return persister;
}
@Override
public boolean equals(Object other) {
if ( this == other ) {

View File

@ -95,13 +95,11 @@ public class SetIdentifierOnAEnhancedProxyTest extends BaseNonConfigCoreFunction
loadedChild.setId( lastChildID );
// ^ should have triggered "base fetch group" initialization which would mean a SQL select
assertEquals( 1, stats.getPrepareStatementCount() );
assertEquals( 0, stats.getPrepareStatementCount() );
// check that the `#setName` "persisted"
assertThat( loadedChild.getId(), is( lastChildID ) );
assertEquals( 1, stats.getPrepareStatementCount() );
assertEquals( 0, stats.getPrepareStatementCount() );
}
);
@ -114,7 +112,6 @@ public class SetIdentifierOnAEnhancedProxyTest extends BaseNonConfigCoreFunction
}
@Ignore
@Test(expected = PersistenceException.class)
public void updateIdTest() {
final Statistics stats = sessionFactory().getStatistics();
@ -133,13 +130,11 @@ public class SetIdentifierOnAEnhancedProxyTest extends BaseNonConfigCoreFunction
loadedChild.setId( updatedId );
// ^ should have triggered "base fetch group" initialization which would mean a SQL select
assertEquals( 1, stats.getPrepareStatementCount() );
assertEquals( 0, stats.getPrepareStatementCount() );
// check that the `#setName` "persisted"
assertThat( loadedChild.getId(), is( updatedId ) );
assertEquals( 1, stats.getPrepareStatementCount() );
assertEquals( 0, stats.getPrepareStatementCount() );
}
);