From 41903f8bd5876b99568c951979a776bbfc758085 Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Fri, 9 Jun 2023 18:30:42 +0200 Subject: [PATCH] HHH-16774 Ensure composite field tracking enhancement works also when @Embedded annotation is missing --- .../ByteBuddyEnhancementContext.java | 5 ++ .../bytebuddy/InlineDirtyCheckingHandler.java | 3 +- .../PersistentAttributeTransformer.java | 3 +- .../dirty/DirtyTrackingEmbeddableTest.java | 59 +++++++++++++++++++ 4 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/dirty/DirtyTrackingEmbeddableTest.java diff --git a/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/ByteBuddyEnhancementContext.java b/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/ByteBuddyEnhancementContext.java index 91d5454ac7..86d78fe01e 100644 --- a/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/ByteBuddyEnhancementContext.java +++ b/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/ByteBuddyEnhancementContext.java @@ -15,6 +15,7 @@ import java.util.stream.Collectors; import org.hibernate.bytecode.enhance.internal.bytebuddy.EnhancerImpl.AnnotatedFieldDescription; import org.hibernate.bytecode.enhance.spi.EnhancementContext; +import jakarta.persistence.Embedded; import net.bytebuddy.description.field.FieldDescription; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; @@ -67,6 +68,10 @@ class ByteBuddyEnhancementContext { return enhancementContext.isPersistentField( field ); } + public boolean isCompositeField(AnnotatedFieldDescription field) { + return isCompositeClass( field.getType().asErasure() ) || field.hasAnnotation( Embedded.class ); + } + public AnnotatedFieldDescription[] order(AnnotatedFieldDescription[] persistentFields) { return (AnnotatedFieldDescription[]) enhancementContext.order( persistentFields ); } diff --git a/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/InlineDirtyCheckingHandler.java b/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/InlineDirtyCheckingHandler.java index 34847c8c4a..5f31af222b 100644 --- a/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/InlineDirtyCheckingHandler.java +++ b/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/InlineDirtyCheckingHandler.java @@ -77,8 +77,7 @@ final class InlineDirtyCheckingHandler implements Implementation, ByteCodeAppend ); } - if ( enhancementContext.isCompositeClass( persistentField.getType().asErasure() ) - && persistentField.hasAnnotation( Embedded.class ) + if ( enhancementContext.isCompositeField( persistentField ) // Don't do composite owner tracking for records && !persistentField.getType().isRecord() ) { diff --git a/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/PersistentAttributeTransformer.java b/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/PersistentAttributeTransformer.java index 5433a6af48..256302cab0 100644 --- a/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/PersistentAttributeTransformer.java +++ b/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/PersistentAttributeTransformer.java @@ -276,8 +276,7 @@ final class PersistentAttributeTransformer implements AsmVisitorWrapper.ForDecla if ( !compositeOwner && !enhancementContext.isMappedSuperclassClass( managedCtClass ) - && enhancedField.hasAnnotation( Embedded.class ) - && enhancementContext.isCompositeClass( enhancedField.getType().asErasure() ) + && enhancementContext.isCompositeField( enhancedField ) && enhancementContext.doDirtyCheckingInline( managedCtClass ) ) { compositeOwner = true; } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/dirty/DirtyTrackingEmbeddableTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/dirty/DirtyTrackingEmbeddableTest.java new file mode 100644 index 0000000000..de67d1d1bf --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/dirty/DirtyTrackingEmbeddableTest.java @@ -0,0 +1,59 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.orm.test.bytecode.enhancement.dirty; + +import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; +import org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils; +import org.hibernate.testing.orm.junit.JiraKey; +import org.junit.Test; +import org.junit.runner.RunWith; + +import jakarta.persistence.Embeddable; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; + +@JiraKey( "HHH-16774" ) +@RunWith( BytecodeEnhancerRunner.class ) +public class DirtyTrackingEmbeddableTest { + + @Test + public void test() { + SimpleEntity entity = new SimpleEntity(); + Address address = new Address(); + entity.address = address; + EnhancerTestUtils.clearDirtyTracking( entity ); + + // testing composite object + address.city = "Arendal"; + EnhancerTestUtils.checkDirtyTracking( entity, "address" ); + EnhancerTestUtils.clearDirtyTracking( entity ); + } + + // --- // + + @Embeddable + private static class Address { + String street1; + String street2; + String city; + String state; + String zip; + String phone; + } + + @Entity + private static class SimpleEntity { + + @Id + Long id; + + String name; + + Address address; + + } +}