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()
|
TypeDescription dispatcherType = persistentFieldAsDefined.getType().isPrimitive()
|
||||||
? persistentFieldAsDefined.getType().asErasure()
|
? persistentFieldAsDefined.getType().asErasure()
|
||||||
: TypeDescription.OBJECT;
|
: 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 )
|
// if ( this.$$_hibernate_getInterceptor() != null )
|
||||||
methodVisitor.visitVarInsn( Opcodes.ALOAD, 0 );
|
methodVisitor.visitVarInsn( Opcodes.ALOAD, 0 );
|
||||||
methodVisitor.visitMethodInsn(
|
methodVisitor.visitMethodInsn(
|
||||||
|
@ -80,6 +85,7 @@ abstract class FieldReaderAppender implements ByteCodeAppender {
|
||||||
methodVisitor.visitVarInsn( Opcodes.ALOAD, 0 );
|
methodVisitor.visitVarInsn( Opcodes.ALOAD, 0 );
|
||||||
methodVisitor.visitLdcInsn( persistentFieldAsDefined.getName() );
|
methodVisitor.visitLdcInsn( persistentFieldAsDefined.getName() );
|
||||||
methodVisitor.visitVarInsn( Opcodes.ALOAD, 0 );
|
methodVisitor.visitVarInsn( Opcodes.ALOAD, 0 );
|
||||||
|
|
||||||
fieldRead( methodVisitor );
|
fieldRead( methodVisitor );
|
||||||
methodVisitor.visitMethodInsn(
|
methodVisitor.visitMethodInsn(
|
||||||
Opcodes.INVOKEINTERFACE,
|
Opcodes.INVOKEINTERFACE,
|
||||||
|
@ -95,7 +101,8 @@ abstract class FieldReaderAppender implements ByteCodeAppender {
|
||||||
);
|
);
|
||||||
// field = (cast) XXX
|
// field = (cast) XXX
|
||||||
if ( !dispatcherType.isPrimitive() ) {
|
if ( !dispatcherType.isPrimitive() ) {
|
||||||
methodVisitor.visitTypeInsn( Opcodes.CHECKCAST, persistentFieldAsDefined.getType().asErasure().getInternalName() );
|
methodVisitor.visitTypeInsn(
|
||||||
|
Opcodes.CHECKCAST, persistentFieldAsDefined.getType().asErasure().getInternalName() );
|
||||||
}
|
}
|
||||||
fieldWrite( methodVisitor );
|
fieldWrite( methodVisitor );
|
||||||
// end if
|
// end if
|
||||||
|
@ -103,6 +110,8 @@ abstract class FieldReaderAppender implements ByteCodeAppender {
|
||||||
if ( implementationContext.getClassFileVersion().isAtLeast( ClassFileVersion.JAVA_V6 ) ) {
|
if ( implementationContext.getClassFileVersion().isAtLeast( ClassFileVersion.JAVA_V6 ) ) {
|
||||||
methodVisitor.visitFrame( Opcodes.F_SAME, 0, null, 0, null );
|
methodVisitor.visitFrame( Opcodes.F_SAME, 0, null, 0, null );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// return field
|
// return field
|
||||||
methodVisitor.visitVarInsn( Opcodes.ALOAD, 0 );
|
methodVisitor.visitVarInsn( Opcodes.ALOAD, 0 );
|
||||||
fieldRead( methodVisitor );
|
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