HHH-15072 Don't enhance records and skip owner tracking for embeddable record fields

This commit is contained in:
Christian Beikov 2022-08-29 18:23:36 +02:00
parent 9f5f31ec97
commit d2cca544c2
3 changed files with 109 additions and 1 deletions

View File

@ -149,6 +149,11 @@ public class EnhancerImpl implements Enhancer {
log.debugf( "Skipping enhancement of [%s]: it's an interface", managedCtClass.getName() ); log.debugf( "Skipping enhancement of [%s]: it's an interface", managedCtClass.getName() );
return null; return null;
} }
// can't effectively enhance records
if ( managedCtClass.isRecord() ) {
log.debugf( "Skipping enhancement of [%s]: it's a record", managedCtClass.getName() );
return null;
}
// skip already enhanced classes // skip already enhanced classes
if ( alreadyEnhanced( managedCtClass ) ) { if ( alreadyEnhanced( managedCtClass ) ) {
log.debugf( "Skipping enhancement of [%s]: already enhanced", managedCtClass.getName() ); log.debugf( "Skipping enhancement of [%s]: already enhanced", managedCtClass.getName() );

View File

@ -62,7 +62,9 @@ final class InlineDirtyCheckingHandler implements Implementation, ByteCodeAppend
} }
if ( enhancementContext.isCompositeClass( persistentField.getType().asErasure() ) if ( enhancementContext.isCompositeClass( persistentField.getType().asErasure() )
&& persistentField.hasAnnotation( Embedded.class ) ) { && persistentField.hasAnnotation( Embedded.class )
// Don't do composite owner tracking for records
&& !persistentField.getType().isRecord() ) {
// HHH-13759 - Call getter on superclass if field is not visible // HHH-13759 - Call getter on superclass if field is not visible
// An embedded field won't be visible if declared private in a superclass // An embedded field won't be visible if declared private in a superclass

View File

@ -0,0 +1,101 @@
/*
* 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.records;
import org.hibernate.engine.spi.ManagedComposite;
import org.hibernate.engine.spi.ManagedEntity;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.EnhancementOptions;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.hibernate.testing.orm.junit.JiraKey;
import org.junit.Test;
import org.junit.runner.RunWith;
import jakarta.persistence.Embeddable;
import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@JiraKey( "HHH-15072" )
@RunWith( BytecodeEnhancerRunner.class )
@EnhancementOptions(lazyLoading = true, extendedEnhancement = true, inlineDirtyChecking = true)
public class RecordAsEmbeddableEnhancementTest extends BaseCoreFunctionalTestCase {
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { MyEntity.class };
}
@Test
public void test() {
// Ensure entity is enhanced, but not the record class
assertTrue( ManagedEntity.class.isAssignableFrom( MyEntity.class ) );
assertFalse( ManagedComposite.class.isAssignableFrom( MyRecord.class ) );
doInHibernate(
this::sessionFactory,
session -> {
session.persist( new MyEntity( 1L, new MyRecord( "test", "abc" ) ) );
}
);
doInHibernate(
this::sessionFactory,
session -> {
MyEntity myEntity = session.get( MyEntity.class, 1L );
assertNotNull( myEntity );
assertEquals( "test", myEntity.getRecord().name() );
assertEquals( "abc", myEntity.getRecord().description() );
myEntity.setRecord( new MyRecord( "test2", "def" ) );
}
);
}
@Entity(name = "MyEntity")
public static class MyEntity {
@Id
Long id;
@Embedded
MyRecord record;
public MyEntity() {
}
public MyEntity(Long id, MyRecord record) {
this.id = id;
this.record = record;
}
public Long getId() {
return id;
}
public MyRecord getRecord() {
return record;
}
public void setId(Long id) {
this.id = id;
}
public void setRecord(MyRecord record) {
this.record = record;
}
}
@Embeddable
public static record MyRecord(String name, String description) {}
}