HHH-16774 Ensure composite field tracking enhancement works also when @Embedded annotation is missing

This commit is contained in:
Christian Beikov 2023-06-09 18:30:42 +02:00
parent 47eb862e06
commit f0ebb55026
4 changed files with 66 additions and 4 deletions

View File

@ -15,6 +15,7 @@ import java.util.stream.Collectors;
import org.hibernate.bytecode.enhance.internal.bytebuddy.EnhancerImpl.AnnotatedFieldDescription; import org.hibernate.bytecode.enhance.internal.bytebuddy.EnhancerImpl.AnnotatedFieldDescription;
import org.hibernate.bytecode.enhance.spi.EnhancementContext; import org.hibernate.bytecode.enhance.spi.EnhancementContext;
import jakarta.persistence.Embedded;
import net.bytebuddy.description.field.FieldDescription; import net.bytebuddy.description.field.FieldDescription;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
@ -67,6 +68,10 @@ class ByteBuddyEnhancementContext {
return enhancementContext.isPersistentField( field ); return enhancementContext.isPersistentField( field );
} }
public boolean isCompositeField(AnnotatedFieldDescription field) {
return isCompositeClass( field.getType().asErasure() ) || field.hasAnnotation( Embedded.class );
}
public AnnotatedFieldDescription[] order(AnnotatedFieldDescription[] persistentFields) { public AnnotatedFieldDescription[] order(AnnotatedFieldDescription[] persistentFields) {
return (AnnotatedFieldDescription[]) enhancementContext.order( persistentFields ); return (AnnotatedFieldDescription[]) enhancementContext.order( persistentFields );
} }

View File

@ -77,8 +77,7 @@ final class InlineDirtyCheckingHandler implements Implementation, ByteCodeAppend
); );
} }
if ( enhancementContext.isCompositeClass( persistentField.getType().asErasure() ) if ( enhancementContext.isCompositeField( persistentField )
&& persistentField.hasAnnotation( Embedded.class )
// Don't do composite owner tracking for records // Don't do composite owner tracking for records
&& !persistentField.getType().isRecord() ) { && !persistentField.getType().isRecord() ) {

View File

@ -276,8 +276,7 @@ final class PersistentAttributeTransformer implements AsmVisitorWrapper.ForDecla
if ( !compositeOwner if ( !compositeOwner
&& !enhancementContext.isMappedSuperclassClass( managedCtClass ) && !enhancementContext.isMappedSuperclassClass( managedCtClass )
&& enhancedField.hasAnnotation( Embedded.class ) && enhancementContext.isCompositeField( enhancedField )
&& enhancementContext.isCompositeClass( enhancedField.getType().asErasure() )
&& enhancementContext.doDirtyCheckingInline( managedCtClass ) ) { && enhancementContext.doDirtyCheckingInline( managedCtClass ) ) {
compositeOwner = true; compositeOwner = true;
} }

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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;
}
}