HHH-17418 Change field reader for private final fields
This commit is contained in:
parent
ef4609baad
commit
638e8b857a
|
@ -54,6 +54,11 @@ abstract class FieldReaderAppender implements ByteCodeAppender {
|
|||
TypeDescription dispatcherType = persistentFieldAsDefined.getType().isPrimitive()
|
||||
? persistentFieldAsDefined.getType().asErasure()
|
||||
: TypeDescription.OBJECT;
|
||||
// From `PersistentAttributeTransformer`:
|
||||
// Final fields will only be written to from the constructor,
|
||||
// so there's no point trying to replace final field writes with a method call.
|
||||
// as a result if a field is final then there will be no write method, and we don't want to have this block:
|
||||
if ( !persistentField.asDefined().isFinal() ) {
|
||||
// if ( this.$$_hibernate_getInterceptor() != null )
|
||||
methodVisitor.visitVarInsn( Opcodes.ALOAD, 0 );
|
||||
methodVisitor.visitMethodInsn(
|
||||
|
@ -80,6 +85,7 @@ abstract class FieldReaderAppender implements ByteCodeAppender {
|
|||
methodVisitor.visitVarInsn( Opcodes.ALOAD, 0 );
|
||||
methodVisitor.visitLdcInsn( persistentFieldAsDefined.getName() );
|
||||
methodVisitor.visitVarInsn( Opcodes.ALOAD, 0 );
|
||||
|
||||
fieldRead( methodVisitor );
|
||||
methodVisitor.visitMethodInsn(
|
||||
Opcodes.INVOKEINTERFACE,
|
||||
|
@ -95,7 +101,8 @@ abstract class FieldReaderAppender implements ByteCodeAppender {
|
|||
);
|
||||
// field = (cast) XXX
|
||||
if ( !dispatcherType.isPrimitive() ) {
|
||||
methodVisitor.visitTypeInsn( Opcodes.CHECKCAST, persistentFieldAsDefined.getType().asErasure().getInternalName() );
|
||||
methodVisitor.visitTypeInsn(
|
||||
Opcodes.CHECKCAST, persistentFieldAsDefined.getType().asErasure().getInternalName() );
|
||||
}
|
||||
fieldWrite( methodVisitor );
|
||||
// end if
|
||||
|
@ -103,6 +110,8 @@ abstract class FieldReaderAppender implements ByteCodeAppender {
|
|||
if ( implementationContext.getClassFileVersion().isAtLeast( ClassFileVersion.JAVA_V6 ) ) {
|
||||
methodVisitor.visitFrame( Opcodes.F_SAME, 0, null, 0, null );
|
||||
}
|
||||
}
|
||||
|
||||
// return field
|
||||
methodVisitor.visitVarInsn( Opcodes.ALOAD, 0 );
|
||||
fieldRead( methodVisitor );
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
package org.hibernate.orm.test.bytecode.enhancement.superclass;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.hibernate.testing.orm.junit.JiraKey;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.MappedSuperclass;
|
||||
|
||||
@JiraKey("HHH-17418")
|
||||
@RunWith(BytecodeEnhancerRunner.class)
|
||||
public class MappedSuperclassTest extends BaseCoreFunctionalTestCase {
|
||||
private static final LocalDateTime TEST_DATE_UPDATED_VALUE = LocalDateTime.of( 2023, 11, 10, 0, 0 );
|
||||
private static final long TEST_ID = 1L;
|
||||
|
||||
@Override
|
||||
public Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] { MyEntity.class };
|
||||
}
|
||||
|
||||
@Before
|
||||
public void prepare() {
|
||||
doInHibernate( this::sessionFactory, s -> {
|
||||
MyEntity testEntity = new MyEntity();
|
||||
testEntity.id = TEST_ID;
|
||||
s.persist( testEntity );
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
doInHibernate( this::sessionFactory, s -> {
|
||||
MyEntity testEntity = s.get( MyEntity.class, TEST_ID );
|
||||
assertThat( testEntity.value() ).isEqualTo( TEST_DATE_UPDATED_VALUE );
|
||||
} );
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanup() {
|
||||
doInHibernate( this::sessionFactory, s -> {
|
||||
MyEntity testEntity = s.get( MyEntity.class, TEST_ID );
|
||||
s.remove( testEntity );
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
@MappedSuperclass
|
||||
public static class MappedBase {
|
||||
// field is private on purpose so that enhancer will not use field access
|
||||
@Column
|
||||
private final LocalDateTime updated = TEST_DATE_UPDATED_VALUE;
|
||||
|
||||
public LocalDateTime value() {
|
||||
return updated;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity
|
||||
public static class MyEntity extends MappedBase {
|
||||
@Id
|
||||
Long id;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue