HHH-11820 - Simplify dirty tracking on entities without collections [bytebuddy]
This commit is contained in:
parent
c392d20dec
commit
d0e7fab351
|
@ -14,6 +14,7 @@ import java.util.Map;
|
|||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.bytecode.enhance.internal.tracker.CompositeOwnerTracker;
|
||||
import org.hibernate.bytecode.enhance.internal.tracker.DirtyTracker;
|
||||
import org.hibernate.bytecode.enhance.internal.tracker.NoopCollectionTracker;
|
||||
import org.hibernate.bytecode.enhance.internal.tracker.SimpleCollectionTracker;
|
||||
import org.hibernate.bytecode.enhance.internal.tracker.SimpleFieldTracker;
|
||||
import org.hibernate.bytecode.enhance.spi.CollectionTracker;
|
||||
|
@ -83,7 +84,23 @@ class CodeTemplates {
|
|||
}
|
||||
}
|
||||
|
||||
static class AreCollectionFieldsDirty {
|
||||
static class GetDirtyAttributesWithoutCollections {
|
||||
@Advice.OnMethodExit
|
||||
static void $$_hibernate_getDirtyAttributes(
|
||||
@Advice.Return(readOnly = false) String[] returned,
|
||||
@Advice.FieldValue(value = EnhancerConstants.TRACKER_FIELD_NAME) DirtyTracker $$_hibernate_tracker) {
|
||||
returned = $$_hibernate_tracker == null ? new String[0] : $$_hibernate_tracker.get();
|
||||
}
|
||||
}
|
||||
|
||||
static class GetCollectionTrackerWithoutCollections {
|
||||
@Advice.OnMethodExit
|
||||
static void $$_hibernate_getCollectionTracker( @Advice.Return(readOnly = false) CollectionTracker returned) {
|
||||
returned = NoopCollectionTracker.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
static class AreFieldsDirty {
|
||||
@Advice.OnMethodExit
|
||||
static void $$_hibernate_hasDirtyAttributes(
|
||||
@Advice.This ExtendedSelfDirtinessTracker self,
|
||||
|
@ -93,6 +110,15 @@ class CodeTemplates {
|
|||
}
|
||||
}
|
||||
|
||||
static class AreFieldsDirtyWithoutCollections {
|
||||
@Advice.OnMethodExit
|
||||
static void $$_hibernate_hasDirtyAttributes(
|
||||
@Advice.Return(readOnly = false) boolean returned,
|
||||
@Advice.FieldValue(value = EnhancerConstants.TRACKER_FIELD_NAME) DirtyTracker $$_hibernate_tracker) {
|
||||
returned = $$_hibernate_tracker != null && !$$_hibernate_tracker.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
static class ClearDirtyAttributes {
|
||||
@Advice.OnMethodEnter
|
||||
static void $$_hibernate_clearDirtyAttributes(
|
||||
|
@ -105,6 +131,16 @@ class CodeTemplates {
|
|||
}
|
||||
}
|
||||
|
||||
static class ClearDirtyAttributesWithoutCollections {
|
||||
@Advice.OnMethodEnter
|
||||
static void $$_hibernate_clearDirtyAttributes(
|
||||
@Advice.FieldValue(value = EnhancerConstants.TRACKER_FIELD_NAME) DirtyTracker $$_hibernate_tracker) {
|
||||
if ( $$_hibernate_tracker != null ) {
|
||||
$$_hibernate_tracker.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class SuspendDirtyTracking {
|
||||
@Advice.OnMethodEnter
|
||||
static void $$_hibernate_suspendDirtyTracking(
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.hibernate.engine.spi.ManagedEntity;
|
|||
import org.hibernate.engine.spi.ManagedMappedSuperclass;
|
||||
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
|
||||
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
|
||||
import org.hibernate.engine.spi.SelfDirtinessTracker;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
||||
|
@ -58,6 +59,7 @@ import net.bytebuddy.implementation.Implementation;
|
|||
import net.bytebuddy.implementation.StubMethod;
|
||||
import net.bytebuddy.pool.TypePool;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isDefaultFinalizer;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isGetter;
|
||||
|
||||
public class EnhancerImpl implements Enhancer {
|
||||
|
@ -95,7 +97,7 @@ public class EnhancerImpl implements Enhancer {
|
|||
try {
|
||||
final TypeDescription managedCtClass = classPool.describe( className ).resolve();
|
||||
DynamicType.Builder<?> builder = doEnhance(
|
||||
new ByteBuddy().with( TypeValidation.DISABLED ).redefine( managedCtClass, ClassFileLocator.Simple.of( className, originalBytes ) ),
|
||||
new ByteBuddy().ignore( isDefaultFinalizer() ).with( TypeValidation.DISABLED ).redefine( managedCtClass, ClassFileLocator.Simple.of( className, originalBytes ) ),
|
||||
managedCtClass
|
||||
);
|
||||
if ( builder == null ) {
|
||||
|
@ -161,29 +163,48 @@ public class EnhancerImpl implements Enhancer {
|
|||
builder = addInterceptorHandling( builder, managedCtClass );
|
||||
|
||||
if ( enhancementContext.doDirtyCheckingInline( managedCtClass ) ) {
|
||||
builder = builder.implement( ExtendedSelfDirtinessTracker.class )
|
||||
.defineField( EnhancerConstants.TRACKER_FIELD_NAME, DirtyTracker.class, FieldManifestation.TRANSIENT, Visibility.PRIVATE )
|
||||
.annotateField( AnnotationDescription.Builder.ofType( Transient.class ).build() )
|
||||
.defineField( EnhancerConstants.TRACKER_COLLECTION_NAME, CollectionTracker.class, FieldManifestation.TRANSIENT, Visibility.PRIVATE )
|
||||
.annotateField( AnnotationDescription.Builder.ofType( Transient.class ).build() )
|
||||
.defineMethod( EnhancerConstants.TRACKER_CHANGER_NAME, void.class, Visibility.PUBLIC )
|
||||
.withParameters( String.class )
|
||||
.intercept( Advice.to( CodeTemplates.TrackChange.class ).wrap( StubMethod.INSTANCE ) )
|
||||
.defineMethod( EnhancerConstants.TRACKER_GET_NAME, String[].class, Visibility.PUBLIC )
|
||||
.intercept( Advice.to( CodeTemplates.GetDirtyAttributes.class ).wrap( StubMethod.INSTANCE ) )
|
||||
.defineMethod( EnhancerConstants.TRACKER_HAS_CHANGED_NAME, boolean.class, Visibility.PUBLIC )
|
||||
.intercept( Advice.to( CodeTemplates.AreCollectionFieldsDirty.class ).wrap( StubMethod.INSTANCE ) )
|
||||
.defineMethod( EnhancerConstants.TRACKER_CLEAR_NAME, void.class, Visibility.PUBLIC )
|
||||
.intercept( Advice.to( CodeTemplates.ClearDirtyAttributes.class ).wrap( StubMethod.INSTANCE ) )
|
||||
.defineMethod( EnhancerConstants.TRACKER_SUSPEND_NAME, void.class, Visibility.PUBLIC )
|
||||
.withParameters( boolean.class )
|
||||
.intercept( Advice.to( CodeTemplates.SuspendDirtyTracking.class ).wrap( StubMethod.INSTANCE ) )
|
||||
.defineMethod( EnhancerConstants.TRACKER_COLLECTION_GET_NAME, CollectionTracker.class, Visibility.PUBLIC )
|
||||
.intercept( FieldAccessor.ofField( EnhancerConstants.TRACKER_COLLECTION_NAME ) );
|
||||
if ( collectCollectionFields( managedCtClass ).isEmpty() ) {
|
||||
builder = builder.implement( SelfDirtinessTracker.class )
|
||||
.defineField( EnhancerConstants.TRACKER_FIELD_NAME, DirtyTracker.class, FieldManifestation.TRANSIENT, Visibility.PRIVATE )
|
||||
.annotateField( AnnotationDescription.Builder.ofType( Transient.class ).build() )
|
||||
.defineMethod( EnhancerConstants.TRACKER_CHANGER_NAME, void.class, Visibility.PUBLIC )
|
||||
.withParameters( String.class )
|
||||
.intercept( Advice.to( CodeTemplates.TrackChange.class ).wrap( StubMethod.INSTANCE ) )
|
||||
.defineMethod( EnhancerConstants.TRACKER_GET_NAME, String[].class, Visibility.PUBLIC )
|
||||
.intercept( Advice.to( CodeTemplates.GetDirtyAttributesWithoutCollections.class ).wrap( StubMethod.INSTANCE ) )
|
||||
.defineMethod( EnhancerConstants.TRACKER_HAS_CHANGED_NAME, boolean.class, Visibility.PUBLIC )
|
||||
.intercept( Advice.to( CodeTemplates.AreFieldsDirtyWithoutCollections.class ).wrap( StubMethod.INSTANCE ) )
|
||||
.defineMethod( EnhancerConstants.TRACKER_CLEAR_NAME, void.class, Visibility.PUBLIC )
|
||||
.intercept( Advice.to( CodeTemplates.ClearDirtyAttributesWithoutCollections.class ).wrap( StubMethod.INSTANCE ) )
|
||||
.defineMethod( EnhancerConstants.TRACKER_SUSPEND_NAME, void.class, Visibility.PUBLIC )
|
||||
.withParameters( boolean.class )
|
||||
.intercept( Advice.to( CodeTemplates.SuspendDirtyTracking.class ).wrap( StubMethod.INSTANCE ) )
|
||||
.defineMethod( EnhancerConstants.TRACKER_COLLECTION_GET_NAME, CollectionTracker.class, Visibility.PUBLIC )
|
||||
.intercept( Advice.to( CodeTemplates.GetCollectionTrackerWithoutCollections.class ).wrap( StubMethod.INSTANCE ) );
|
||||
}
|
||||
else {
|
||||
builder = builder.implement( ExtendedSelfDirtinessTracker.class )
|
||||
.defineField( EnhancerConstants.TRACKER_FIELD_NAME, DirtyTracker.class, FieldManifestation.TRANSIENT, Visibility.PRIVATE )
|
||||
.annotateField( AnnotationDescription.Builder.ofType( Transient.class ).build() )
|
||||
.defineField( EnhancerConstants.TRACKER_COLLECTION_NAME, CollectionTracker.class, FieldManifestation.TRANSIENT, Visibility.PRIVATE )
|
||||
.annotateField( AnnotationDescription.Builder.ofType( Transient.class ).build() )
|
||||
.defineMethod( EnhancerConstants.TRACKER_CHANGER_NAME, void.class, Visibility.PUBLIC )
|
||||
.withParameters( String.class )
|
||||
.intercept( Advice.to( CodeTemplates.TrackChange.class ).wrap( StubMethod.INSTANCE ) )
|
||||
.defineMethod( EnhancerConstants.TRACKER_GET_NAME, String[].class, Visibility.PUBLIC )
|
||||
.intercept( Advice.to( CodeTemplates.GetDirtyAttributes.class ).wrap( StubMethod.INSTANCE ) )
|
||||
.defineMethod( EnhancerConstants.TRACKER_HAS_CHANGED_NAME, boolean.class, Visibility.PUBLIC )
|
||||
.intercept( Advice.to( CodeTemplates.AreFieldsDirty.class ).wrap( StubMethod.INSTANCE ) )
|
||||
.defineMethod( EnhancerConstants.TRACKER_CLEAR_NAME, void.class, Visibility.PUBLIC )
|
||||
.intercept( Advice.to( CodeTemplates.ClearDirtyAttributes.class ).wrap( StubMethod.INSTANCE ) )
|
||||
.defineMethod( EnhancerConstants.TRACKER_SUSPEND_NAME, void.class, Visibility.PUBLIC )
|
||||
.withParameters( boolean.class )
|
||||
.intercept( Advice.to( CodeTemplates.SuspendDirtyTracking.class ).wrap( StubMethod.INSTANCE ) )
|
||||
.defineMethod( EnhancerConstants.TRACKER_COLLECTION_GET_NAME, CollectionTracker.class, Visibility.PUBLIC )
|
||||
.intercept( FieldAccessor.ofField( EnhancerConstants.TRACKER_COLLECTION_NAME ) );
|
||||
|
||||
Implementation isDirty = StubMethod.INSTANCE, getDirtyNames = StubMethod.INSTANCE, clearDirtyNames = StubMethod.INSTANCE;
|
||||
for ( FieldDescription collectionField : collectCollectionFields( managedCtClass ) ) {
|
||||
if ( !enhancementContext.isMappedCollection( collectionField ) ) {
|
||||
Implementation isDirty = StubMethod.INSTANCE, getDirtyNames = StubMethod.INSTANCE, clearDirtyNames = StubMethod.INSTANCE;
|
||||
for ( FieldDescription collectionField : collectCollectionFields( managedCtClass ) ) {
|
||||
if ( collectionField.getType().asErasure().isAssignableTo( Map.class ) ) {
|
||||
isDirty = Advice.withCustomMapping()
|
||||
.bind( CodeTemplates.FieldName.class, collectionField.getName() )
|
||||
|
@ -219,22 +240,22 @@ public class EnhancerImpl implements Enhancer {
|
|||
.wrap( clearDirtyNames );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( enhancementContext.hasLazyLoadableAttributes( managedCtClass ) ) {
|
||||
clearDirtyNames = Advice.to( CodeTemplates.InitializeLazyAttributeLoadingInterceptor.class ).wrap( clearDirtyNames );
|
||||
}
|
||||
if ( enhancementContext.hasLazyLoadableAttributes( managedCtClass ) ) {
|
||||
clearDirtyNames = Advice.to( CodeTemplates.InitializeLazyAttributeLoadingInterceptor.class ).wrap( clearDirtyNames );
|
||||
}
|
||||
|
||||
builder = builder.defineMethod( EnhancerConstants.TRACKER_COLLECTION_CHANGED_NAME, boolean.class, Visibility.PUBLIC )
|
||||
.intercept( isDirty )
|
||||
.defineMethod( EnhancerConstants.TRACKER_COLLECTION_CHANGED_FIELD_NAME, void.class, Visibility.PUBLIC )
|
||||
.withParameters( DirtyTracker.class )
|
||||
.intercept( getDirtyNames )
|
||||
.defineMethod( EnhancerConstants.TRACKER_COLLECTION_CLEAR_NAME, void.class, Visibility.PUBLIC )
|
||||
.intercept( Advice.withCustomMapping().to( CodeTemplates.ClearDirtyCollectionNames.class ).wrap( StubMethod.INSTANCE ) )
|
||||
.defineMethod( ExtendedSelfDirtinessTracker.REMOVE_DIRTY_FIELDS_NAME, void.class, Visibility.PUBLIC )
|
||||
.withParameters( LazyAttributeLoadingInterceptor.class )
|
||||
.intercept( clearDirtyNames );
|
||||
builder = builder.defineMethod( EnhancerConstants.TRACKER_COLLECTION_CHANGED_NAME, boolean.class, Visibility.PUBLIC )
|
||||
.intercept( isDirty )
|
||||
.defineMethod( EnhancerConstants.TRACKER_COLLECTION_CHANGED_FIELD_NAME, void.class, Visibility.PUBLIC )
|
||||
.withParameters( DirtyTracker.class )
|
||||
.intercept( getDirtyNames )
|
||||
.defineMethod( EnhancerConstants.TRACKER_COLLECTION_CLEAR_NAME, void.class, Visibility.PUBLIC )
|
||||
.intercept( Advice.withCustomMapping().to( CodeTemplates.ClearDirtyCollectionNames.class ).wrap( StubMethod.INSTANCE ) )
|
||||
.defineMethod( ExtendedSelfDirtinessTracker.REMOVE_DIRTY_FIELDS_NAME, void.class, Visibility.PUBLIC )
|
||||
.withParameters( LazyAttributeLoadingInterceptor.class )
|
||||
.intercept( clearDirtyNames );
|
||||
}
|
||||
}
|
||||
|
||||
return transformer.applyTo( builder, false );
|
||||
|
@ -340,7 +361,7 @@ public class EnhancerImpl implements Enhancer {
|
|||
if ( Modifier.isStatic( ctField.getModifiers() ) || ctField.getName().startsWith( "$$_hibernate_" ) ) {
|
||||
continue;
|
||||
}
|
||||
if ( enhancementContext.isPersistentField( ctField ) ) {
|
||||
if ( enhancementContext.isPersistentField( ctField ) && !enhancementContext.isMappedCollection( ctField ) ) {
|
||||
if ( ctField.getType().asErasure().isAssignableTo( Collection.class ) || ctField.getType().asErasure().isAssignableTo( Map.class ) ) {
|
||||
collectionList.add( ctField );
|
||||
}
|
||||
|
@ -368,9 +389,11 @@ public class EnhancerImpl implements Enhancer {
|
|||
List<FieldDescription> collectionList = new ArrayList<FieldDescription>();
|
||||
|
||||
for ( FieldDescription ctField : managedCtSuperclass.getDeclaredFields() ) {
|
||||
if ( !Modifier.isStatic( ctField.getModifiers() ) && enhancementContext.isPersistentField( ctField ) ) {
|
||||
if ( ctField.getType().asErasure().isAssignableTo( Collection.class ) || ctField.getType().asErasure().isAssignableTo( Map.class ) ) {
|
||||
collectionList.add( ctField );
|
||||
if ( !Modifier.isStatic( ctField.getModifiers() ) ) {
|
||||
if ( enhancementContext.isPersistentField( ctField ) && !enhancementContext.isMappedCollection( ctField ) ) {
|
||||
if ( ctField.getType().asErasure().isAssignableTo( Collection.class ) || ctField.getType().asErasure().isAssignableTo( Map.class ) ) {
|
||||
collectionList.add( ctField );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue