HHH-13653 Uninitialized entity does not get initialized when a setter is called with enhancement-as-proxy enabled

(cherry picked from commit 3c1f4356dd3a6e6d88ee4a9442119f262b6dfb97)
This commit is contained in:
Andrea Boriero 2019-10-04 16:41:07 +01:00 committed by gbadner
parent b788b62e08
commit 20beec97c1
3 changed files with 17 additions and 10 deletions

View File

@ -6,7 +6,6 @@
*/
package org.hibernate.bytecode.enhance.spi.interceptor;
import java.io.Serializable;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
@ -40,6 +39,8 @@ public class EnhancementAsProxyLazinessInterceptor extends AbstractLazyLoadInter
private boolean initialized;
private boolean initializeBeforeWrite;
public EnhancementAsProxyLazinessInterceptor(
String entityName,
Set<String> identifierAttributeNames,
@ -59,6 +60,9 @@ public EnhancementAsProxyLazinessInterceptor(
final EntityPersister entityPersister = session.getFactory().getMetamodel().entityPersister( entityName );
this.inLineDirtyChecking = entityPersister.getEntityMode() == EntityMode.POJO
&& SelfDirtinessTracker.class.isAssignableFrom( entityPersister.getMappedClass() );
// if self-dirty tracking is enabled but DynamicUpdate is not enabled then we need to initialise the entity
// because the pre-computed update statement contains even not dirty properties and so we need all the values
initializeBeforeWrite = !inLineDirtyChecking || !entityPersister.getEntityMetamodel().isDynamicUpdate();
}
public EntityKey getEntityKey() {
@ -89,7 +93,7 @@ protected Object handleRead(Object target, String attributeName, Object value) {
.entityPersister( getEntityName() );
final EntityTuplizer entityTuplizer = entityPersister.getEntityTuplizer();
if ( inLineDirtyChecking && writtenFieldNames != null && !writtenFieldNames.isEmpty() ) {
if ( writtenFieldNames != null && !writtenFieldNames.isEmpty() ) {
// enhancement has dirty-tracking available and at least one attribute was explicitly set
@ -241,7 +245,7 @@ protected Object handleWrite(Object target, String attributeName, Object oldValu
return newValue;
}
if ( ! inLineDirtyChecking ) {
if ( initializeBeforeWrite ) {
// we need to force-initialize the proxy - the fetch group to which the `attributeName` belongs
try {
forceInitialize( target, attributeName );
@ -249,6 +253,10 @@ protected Object handleWrite(Object target, String attributeName, Object oldValu
finally {
initialized = true;
}
if ( inLineDirtyChecking ) {
( (SelfDirtinessTracker) target ).$$_hibernate_trackChange( attributeName );
}
}
else {
// because of the entity being enhanced with `org.hibernate.engine.spi.SelfDirtinessTracker`

View File

@ -91,7 +91,6 @@ public void testInitializeWithGetter() {
}
@Test
@FailureExpected( jiraKey = "HHH-13653")
public void testInitializeWithSetter() {
inTransaction(
session -> {

View File

@ -115,13 +115,13 @@ public void updateSimpleField() {
MatcherAssert.assertThat( interceptor, instanceOf( EnhancementAsProxyLazinessInterceptor.class ) );
loadedChild.setName( updatedName );
assertEquals( 0, stats.getPrepareStatementCount() );
assertEquals( 1, stats.getPrepareStatementCount() );
assertThat( loadedChild.getName(), is( updatedName ) );
assertEquals( 0, stats.getPrepareStatementCount() );
assertEquals( 1, stats.getPrepareStatementCount() );
} );
// the UPDATE
assertEquals( 1, stats.getPrepareStatementCount() );
assertEquals( 2, stats.getPrepareStatementCount() );
doInHibernate( this::sessionFactory, s -> {
Child loadedChild = s.load( Child.class, lastChildID );
@ -143,11 +143,11 @@ public void testUpdateAssociation() {
Parent parent = new Parent();
parent.setName( parentName );
assertEquals( 0, stats.getPrepareStatementCount() );
assertEquals( 1, stats.getPrepareStatementCount() );
loadedChild.setParent( parent );
assertEquals( 0, stats.getPrepareStatementCount() );
assertEquals( 1, stats.getPrepareStatementCount() );
assertThat( loadedChild.getParent().getName(), is( parentName ) );
assertEquals( 0, stats.getPrepareStatementCount() );
assertEquals( 1, stats.getPrepareStatementCount() );
s.save( parent );
} );