HHH-15790 Apply the new type-cache enhancements to CompositeTracker and CompositeOwner

This commit is contained in:
Sanne Grinovero 2022-11-30 16:39:29 +00:00 committed by Sanne Grinovero
parent 3028299b4a
commit 366a1e9c1d
8 changed files with 100 additions and 10 deletions

View File

@ -37,6 +37,8 @@ import net.bytebuddy.implementation.bytecode.member.MethodInvocation;
import net.bytebuddy.implementation.bytecode.member.MethodVariableAccess; import net.bytebuddy.implementation.bytecode.member.MethodVariableAccess;
import net.bytebuddy.jar.asm.Opcodes; import net.bytebuddy.jar.asm.Opcodes;
import static org.hibernate.engine.internal.ManagedTypeHelper.asCompositeTracker;
class CodeTemplates { class CodeTemplates {
static class SetOwner { static class SetOwner {
@ -319,14 +321,14 @@ class CodeTemplates {
@Advice.OnMethodEnter @Advice.OnMethodEnter
static void enter(@FieldName String fieldName, @FieldValue Object field) { static void enter(@FieldName String fieldName, @FieldValue Object field) {
if ( field != null ) { if ( field != null ) {
( (CompositeTracker) field ).$$_hibernate_clearOwner( fieldName ); asCompositeTracker( field ).$$_hibernate_clearOwner( fieldName );
} }
} }
@Advice.OnMethodExit @Advice.OnMethodExit
static void exit(@Advice.This CompositeOwner self, @FieldName String fieldName, @FieldValue Object field) { static void exit(@Advice.This CompositeOwner self, @FieldName String fieldName, @FieldValue Object field) {
if ( field != null ) { if ( field != null ) {
( (CompositeTracker) field ).$$_hibernate_setOwner( fieldName, self ); asCompositeTracker( field ).$$_hibernate_setOwner( fieldName, self );
} }
self.$$_hibernate_trackChange( fieldName ); self.$$_hibernate_trackChange( fieldName );
} }

View File

@ -22,6 +22,7 @@ import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.CompositeType; import org.hibernate.type.CompositeType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import static org.hibernate.engine.internal.ManagedTypeHelper.asSelfDirtinessTracker;
import static org.hibernate.engine.internal.ManagedTypeHelper.isSelfDirtinessTrackerType; import static org.hibernate.engine.internal.ManagedTypeHelper.isSelfDirtinessTrackerType;
/** /**
@ -280,7 +281,7 @@ public class EnhancementAsProxyLazinessInterceptor extends AbstractLazyLoadInter
} }
if ( inLineDirtyChecking ) { if ( inLineDirtyChecking ) {
( (SelfDirtinessTracker) target ).$$_hibernate_trackChange( attributeName ); asSelfDirtinessTracker( target ).$$_hibernate_trackChange( attributeName );
} }
} }
else { else {
@ -293,7 +294,7 @@ public class EnhancementAsProxyLazinessInterceptor extends AbstractLazyLoadInter
} }
writtenFieldNames.add( attributeName ); writtenFieldNames.add( attributeName );
( (SelfDirtinessTracker) target ).$$_hibernate_trackChange( attributeName ); asSelfDirtinessTracker( target ).$$_hibernate_trackChange( attributeName );
} }
return newValue; return newValue;

View File

@ -6,6 +6,8 @@
*/ */
package org.hibernate.engine.internal; package org.hibernate.engine.internal;
import org.hibernate.engine.spi.CompositeOwner;
import org.hibernate.engine.spi.CompositeTracker;
import org.hibernate.engine.spi.PrimeAmongSecondarySupertypes; import org.hibernate.engine.spi.PrimeAmongSecondarySupertypes;
import org.hibernate.engine.spi.Managed; import org.hibernate.engine.spi.Managed;
import org.hibernate.engine.spi.ManagedEntity; import org.hibernate.engine.spi.ManagedEntity;
@ -128,6 +130,29 @@ public final class ManagedTypeHelper {
return false; return false;
} }
/**
* @param entity
* @return true if and only if the entity implements {@see CompositeOwner}
*/
public static boolean isCompositeOwner(final Object entity) {
if ( entity instanceof PrimeAmongSecondarySupertypes ) {
PrimeAmongSecondarySupertypes t = (PrimeAmongSecondarySupertypes) entity;
return t.asCompositeOwner() != null;
}
return false;
}
/**
* @param entity
* @return true if and only if the entity implements {@see CompositeTracker}
*/
public static boolean isCompositeTracker(final Object entity) {
if ( entity instanceof PrimeAmongSecondarySupertypes ) {
PrimeAmongSecondarySupertypes t = (PrimeAmongSecondarySupertypes) entity;
return t.asCompositeTracker() != null;
}
return false;
}
/** /**
* Helper to execute an action on an entity, but exclusively if it's implementing the {@see PersistentAttributeInterceptable} * Helper to execute an action on an entity, but exclusively if it's implementing the {@see PersistentAttributeInterceptable}
@ -248,6 +273,43 @@ public final class ManagedTypeHelper {
throw new ClassCastException( "Object of type '" + entity.getClass() + "' can't be cast to ManagedEntity" ); throw new ClassCastException( "Object of type '" + entity.getClass() + "' can't be cast to ManagedEntity" );
} }
/**
* Cast the object to CompositeTracker
* (using this is highly preferrable over a direct cast)
* @param entity the entity to cast
* @return the same instance after casting
* @throws ClassCastException if it's not of the right type
*/
public static CompositeTracker asCompositeTracker(final Object entity) {
Objects.requireNonNull( entity );
if ( entity instanceof PrimeAmongSecondarySupertypes ) {
PrimeAmongSecondarySupertypes t = (PrimeAmongSecondarySupertypes) entity;
final CompositeTracker e = t.asCompositeTracker();
if ( e != null ) {
return e;
}
}
throw new ClassCastException( "Object of type '" + entity.getClass() + "' can't be cast to CompositeTracker" );
}
/**
* Cast the object to CompositeOwner
* (using this is highly preferrable over a direct cast)
* @param entity the entity to cast
* @return the same instance after casting
* @throws ClassCastException if it's not of the right type
*/
public static CompositeOwner asCompositeOwner(final Object entity) {
Objects.requireNonNull( entity );
if ( entity instanceof PrimeAmongSecondarySupertypes ) {
PrimeAmongSecondarySupertypes t = (PrimeAmongSecondarySupertypes) entity;
final CompositeOwner e = t.asCompositeOwner();
if ( e != null ) {
return e;
}
}
throw new ClassCastException( "Object of type '" + entity.getClass() + "' can't be cast to CompositeOwner" );
}
/** /**
* Cast the object to SelfDirtinessTracker * Cast the object to SelfDirtinessTracker
* (using this is highly preferrable over a direct cast) * (using this is highly preferrable over a direct cast)

View File

@ -9,9 +9,15 @@ package org.hibernate.engine.spi;
/** /**
* @author <a href="mailto:stale.pedersen@jboss.org">Ståle W. Pedersen</a> * @author <a href="mailto:stale.pedersen@jboss.org">Ståle W. Pedersen</a>
*/ */
public interface CompositeOwner { public interface CompositeOwner extends PrimeAmongSecondarySupertypes {
/** /**
* @param attributeName to be added to the dirty list * @param attributeName to be added to the dirty list
*/ */
void $$_hibernate_trackChange(String attributeName); void $$_hibernate_trackChange(String attributeName);
@Override
default CompositeOwner asCompositeOwner() {
return this;
}
} }

View File

@ -9,9 +9,15 @@ package org.hibernate.engine.spi;
/** /**
* @author <a href="mailto:stale.pedersen@jboss.org">Ståle W. Pedersen</a> * @author <a href="mailto:stale.pedersen@jboss.org">Ståle W. Pedersen</a>
*/ */
public interface CompositeTracker { public interface CompositeTracker extends PrimeAmongSecondarySupertypes {
void $$_hibernate_setOwner(String name, CompositeOwner tracker); void $$_hibernate_setOwner(String name, CompositeOwner tracker);
void $$_hibernate_clearOwner(String name); void $$_hibernate_clearOwner(String name);
@Override
default CompositeTracker asCompositeTracker() {
return this;
}
} }

View File

@ -45,4 +45,12 @@ public interface PrimeAmongSecondarySupertypes {
return null; return null;
} }
default CompositeOwner asCompositeOwner() {
return null;
}
default CompositeTracker asCompositeTracker() {
return null;
}
} }

View File

@ -273,6 +273,7 @@ import org.hibernate.type.Type;
import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.java.MutabilityPlan; import org.hibernate.type.descriptor.java.MutabilityPlan;
import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable;
import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable; import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable;
import static org.hibernate.engine.internal.ManagedTypeHelper.processIfPersistentAttributeInterceptable; import static org.hibernate.engine.internal.ManagedTypeHelper.processIfPersistentAttributeInterceptable;
import static org.hibernate.engine.internal.ManagedTypeHelper.processIfSelfDirtinessTracker; import static org.hibernate.engine.internal.ManagedTypeHelper.processIfSelfDirtinessTracker;
@ -1370,7 +1371,7 @@ public abstract class AbstractEntityPersister
public Object initializeLazyProperty(String fieldName, Object entity, SharedSessionContractImplementor session) { public Object initializeLazyProperty(String fieldName, Object entity, SharedSessionContractImplementor session) {
final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
final EntityEntry entry = persistenceContext.getEntry( entity ); final EntityEntry entry = persistenceContext.getEntry( entity );
final PersistentAttributeInterceptor interceptor = ( (PersistentAttributeInterceptable) entity ).$$_hibernate_getInterceptor(); final PersistentAttributeInterceptor interceptor = asPersistentAttributeInterceptable( entity ).$$_hibernate_getInterceptor();
assert interceptor != null : "Expecting bytecode interceptor to be non-null"; assert interceptor != null : "Expecting bytecode interceptor to be non-null";
if ( hasCollections() ) { if ( hasCollections() ) {
@ -1494,7 +1495,7 @@ public abstract class AbstractEntityPersister
throw new AssertionFailure( "no lazy properties" ); throw new AssertionFailure( "no lazy properties" );
} }
final PersistentAttributeInterceptor interceptor = ( (PersistentAttributeInterceptable) entity ).$$_hibernate_getInterceptor(); final PersistentAttributeInterceptor interceptor = asPersistentAttributeInterceptable( entity ).$$_hibernate_getInterceptor();
assert interceptor != null : "Expecting bytecode interceptor to be non-null"; assert interceptor != null : "Expecting bytecode interceptor to be non-null";
LOG.tracef( "Initializing lazy properties from datastore (triggered for `%s`)", fieldName ); LOG.tracef( "Initializing lazy properties from datastore (triggered for `%s`)", fieldName );

View File

@ -10,12 +10,16 @@ import java.io.Serializable;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import org.hibernate.bytecode.enhance.spi.interceptor.BytecodeLazyAttributeInterceptor; import org.hibernate.bytecode.enhance.spi.interceptor.BytecodeLazyAttributeInterceptor;
import org.hibernate.engine.internal.ManagedTypeHelper;
import org.hibernate.engine.spi.CompositeOwner; import org.hibernate.engine.spi.CompositeOwner;
import org.hibernate.engine.spi.CompositeTracker; import org.hibernate.engine.spi.CompositeTracker;
import org.hibernate.engine.spi.PersistentAttributeInterceptor; import org.hibernate.engine.spi.PersistentAttributeInterceptor;
import org.hibernate.property.access.internal.AbstractFieldSerialForm; import org.hibernate.property.access.internal.AbstractFieldSerialForm;
import static org.hibernate.engine.internal.ManagedTypeHelper.asCompositeOwner;
import static org.hibernate.engine.internal.ManagedTypeHelper.asCompositeTracker;
import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable; import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable;
import static org.hibernate.engine.internal.ManagedTypeHelper.isCompositeTracker;
import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptableType; import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptableType;
/** /**
@ -49,8 +53,8 @@ public class EnhancedSetterImpl extends SetterFieldImpl {
super.set( target, value ); super.set( target, value );
// This sets the component relation for dirty tracking purposes // This sets the component relation for dirty tracking purposes
if ( ( enhancementState & COMPOSITE_OWNER ) != 0 && ( ( enhancementState & COMPOSITE_TRACKER_MASK ) != 0 && value != null || value instanceof CompositeTracker ) ) { if ( ( enhancementState & COMPOSITE_OWNER ) != 0 && ( ( enhancementState & COMPOSITE_TRACKER_MASK ) != 0 && value != null || isCompositeTracker( value ) ) ) {
( (CompositeTracker) value ).$$_hibernate_setOwner( propertyName, (CompositeOwner) target ); asCompositeTracker( value ).$$_hibernate_setOwner( propertyName, asCompositeOwner( target ) );
} }
// This marks the attribute as initialized, so it doesn't get lazily loaded afterwards // This marks the attribute as initialized, so it doesn't get lazily loaded afterwards