HHH-12579 Use the field description with type variables resolved to cast the return value of the $$_hibernate_read_<property>() method

This commit is contained in:
Guillaume Smet 2018-05-24 14:17:12 +02:00 committed by Yoann Rodière
parent b4c720871f
commit c0652a5359
2 changed files with 85 additions and 9 deletions

View File

@ -24,19 +24,22 @@ abstract class FieldReaderAppender implements ByteCodeAppender {
protected final TypeDescription managedCtClass;
protected final FieldDescription persistentFieldAsDefined;
protected final FieldDescription persistentField;
private FieldReaderAppender(TypeDescription managedCtClass, FieldDescription.InDefinedShape persistentFieldAsDefined) {
protected final FieldDescription.InDefinedShape persistentFieldAsDefined;
private FieldReaderAppender(TypeDescription managedCtClass, FieldDescription persistentField) {
this.managedCtClass = managedCtClass;
this.persistentFieldAsDefined = persistentFieldAsDefined;
this.persistentField = persistentField;
this.persistentFieldAsDefined = persistentField.asDefined();
}
static ByteCodeAppender of(TypeDescription managedCtClass, FieldDescription persistentField) {
if ( !persistentField.isVisibleTo( managedCtClass ) ) {
return new MethodDispatching( managedCtClass, persistentField.asDefined() );
return new MethodDispatching( managedCtClass, persistentField );
}
else {
return new FieldWriting( managedCtClass, persistentField.asDefined() );
return new FieldWriting( managedCtClass, persistentField );
}
}
@ -100,6 +103,10 @@ abstract class FieldReaderAppender implements ByteCodeAppender {
// return field
methodVisitor.visitVarInsn( Opcodes.ALOAD, 0 );
fieldRead( methodVisitor );
if ( !persistentField.getType().isPrimitive()
&& !persistentField.getType().asErasure().getInternalName().equals( persistentFieldAsDefined.getType().asErasure().getInternalName() ) ) {
methodVisitor.visitTypeInsn( Opcodes.CHECKCAST, persistentField.getType().asErasure().getInternalName() );
}
methodVisitor.visitInsn( Type.getType( persistentFieldAsDefined.getType().asErasure().getDescriptor() ).getOpcode( Opcodes.IRETURN ) );
return new Size( 4 + persistentFieldAsDefined.getType().getStackSize().getSize(), instrumentedMethod.getStackSize() );
}
@ -110,8 +117,8 @@ abstract class FieldReaderAppender implements ByteCodeAppender {
private static class FieldWriting extends FieldReaderAppender {
private FieldWriting(TypeDescription managedCtClass, FieldDescription.InDefinedShape persistentFieldAsDefined) {
super( managedCtClass, persistentFieldAsDefined );
private FieldWriting(TypeDescription managedCtClass, FieldDescription persistentField) {
super( managedCtClass, persistentField );
}
@Override
@ -137,8 +144,8 @@ abstract class FieldReaderAppender implements ByteCodeAppender {
private static class MethodDispatching extends FieldReaderAppender {
private MethodDispatching(TypeDescription managedCtClass, FieldDescription.InDefinedShape persistentFieldAsDefined) {
super( managedCtClass, persistentFieldAsDefined );
private MethodDispatching(TypeDescription managedCtClass, FieldDescription persistentField) {
super( managedCtClass, persistentField );
}
@Override

View File

@ -0,0 +1,69 @@
/*
* 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.test.bytecode.enhancement.basic;
import static org.junit.Assert.assertEquals;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BytecodeEnhancerRunner.class)
public class GenericReturnValueMappedSuperclassEnhancementTest {
@Test
@TestForIssue(jiraKey = "HHH-12579")
public void enhanceClassWithGenericReturnValueOnMappedSuperclass() {
SimpleEntity implementation = new SimpleEntity();
implementation.setEntity( SimpleEntity.Type.ONE );
assertEquals( SimpleEntity.Type.ONE, implementation.getEntity() );
}
@MappedSuperclass
@Cache(usage = CacheConcurrencyStrategy.NONE)
public static class AbstractMappedSuperclassWithGenericReturnValue<T extends Marker> {
@Id
@GeneratedValue
public int id;
@Access(AccessType.PROPERTY)
private T entity;
public T getEntity() {
return entity;
}
public void setEntity(T entity) {
this.entity = entity;
}
}
public interface Marker {
}
@Entity
@Cache(usage = CacheConcurrencyStrategy.NONE)
public static class SimpleEntity extends AbstractMappedSuperclassWithGenericReturnValue<SimpleEntity.Type> {
public enum Type implements Marker {
ONE
}
}
}