HHH-18832 Don't skip bytecode enhancement just because an entity has a `@Transient` getter
This commit is contained in:
parent
9c96e84a58
commit
74c5c844c0
|
@ -462,6 +462,11 @@ public class EnhancerImpl implements Enhancer {
|
||||||
// convert field letter to lower case
|
// convert field letter to lower case
|
||||||
methodFieldName = methodFieldName.substring(0, 1).toLowerCase() + methodFieldName.substring(1);
|
methodFieldName = methodFieldName.substring(0, 1).toLowerCase() + methodFieldName.substring(1);
|
||||||
TypeList typeList = methodDescription.getDeclaredAnnotations().asTypeList();
|
TypeList typeList = methodDescription.getDeclaredAnnotations().asTypeList();
|
||||||
|
if (typeList.stream().anyMatch(typeDefinitions ->
|
||||||
|
(typeDefinitions.getName().equals("jakarta.persistence.Transient")))) {
|
||||||
|
// transient property so ignore it
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (typeList.stream().anyMatch(typeDefinitions ->
|
if (typeList.stream().anyMatch(typeDefinitions ->
|
||||||
(typeDefinitions.getName().contains("jakarta.persistence")))) {
|
(typeDefinitions.getName().contains("jakarta.persistence")))) {
|
||||||
propertyHasAnnotation = true;
|
propertyHasAnnotation = true;
|
||||||
|
|
|
@ -4,9 +4,19 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.orm.test.bytecode.enhancement.access;
|
package org.hibernate.orm.test.bytecode.enhancement.access;
|
||||||
|
|
||||||
import jakarta.persistence.*;
|
import jakarta.persistence.Access;
|
||||||
|
import jakarta.persistence.AccessType;
|
||||||
|
import jakarta.persistence.Basic;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import jakarta.persistence.Transient;
|
||||||
import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced;
|
import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced;
|
||||||
import org.hibernate.testing.orm.junit.*;
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.FailureExpected;
|
||||||
|
import org.hibernate.testing.orm.junit.JiraKey;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
@ -15,16 +25,17 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
@DomainModel(
|
@DomainModel(
|
||||||
annotatedClasses = {
|
annotatedClasses = {
|
||||||
InvalidPropertyNameTest.SomeEntity.class,
|
InvalidPropertyNameTest.SomeEntity.class,
|
||||||
|
InvalidPropertyNameTest.SomeEntityWithFalsePositive.class
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@SessionFactory
|
@SessionFactory
|
||||||
@JiraKey("HHH-16572")
|
|
||||||
@BytecodeEnhanced
|
@BytecodeEnhanced
|
||||||
public class InvalidPropertyNameTest {
|
public class InvalidPropertyNameTest {
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@FailureExpected(jiraKey = "HHH-16572")
|
@FailureExpected(jiraKey = "HHH-16572")
|
||||||
|
@JiraKey("HHH-16572")
|
||||||
public void test(SessionFactoryScope scope) {
|
public void test(SessionFactoryScope scope) {
|
||||||
scope.inTransaction( session -> {
|
scope.inTransaction( session -> {
|
||||||
session.persist( new SomeEntity( 1L, "field", "property" ) );
|
session.persist( new SomeEntity( 1L, "field", "property" ) );
|
||||||
|
@ -43,15 +54,40 @@ public class InvalidPropertyNameTest {
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterEach
|
@Test
|
||||||
public void cleanup(SessionFactoryScope scope) {
|
@JiraKey("HHH-18832")
|
||||||
// uncomment the following when @FailureExpected is removed above
|
public void testNoFalsePositive(SessionFactoryScope scope) {
|
||||||
// scope.inTransaction( session -> {
|
scope.inTransaction( session -> {
|
||||||
// session.remove( session.get( SomeEntity.class, 1L ) );
|
session.persist( new SomeEntityWithFalsePositive( 1L, "property1-initial", "property2-initial" ) );
|
||||||
// PropertyAccessTest} );
|
} );
|
||||||
|
|
||||||
|
// Before HHH-18832 was fixed, lazy-loading enhancement was (incorrectly) skipped,
|
||||||
|
// resulting at best in `property1` being null in the code below,
|
||||||
|
// at worst in other errors such as java.lang.NoSuchMethodError: 'java.lang.String org.hibernate.orm.test.bytecode.enhancement.access.InvalidPropertyNameTest$SomeEntityWithFalsePositive.$$_hibernate_read_property1()'
|
||||||
|
// (see https://hibernate.zulipchat.com/#narrow/channel/132094-hibernate-orm-dev/topic/HHH-16572/near/481330806)
|
||||||
|
scope.inTransaction( session -> {
|
||||||
|
SomeEntityWithFalsePositive entity = session.getReference( SomeEntityWithFalsePositive.class, 1L );
|
||||||
|
// Lazy-loading triggered by field access
|
||||||
|
// Proves bytecode enhancement is effective
|
||||||
|
assertThat( entity.property1 ).isEqualTo( "property1-initial" );
|
||||||
|
} );
|
||||||
|
|
||||||
|
scope.inTransaction( session -> {
|
||||||
|
SomeEntityWithFalsePositive entity = session.getReference( SomeEntityWithFalsePositive.class, 1L );
|
||||||
|
// Proves bytecode enhancement is effective even for the transient method
|
||||||
|
assertThat( entity.getProperty() ).isEqualTo( "property1-initial property2-initial" );
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity
|
@AfterEach
|
||||||
|
public void cleanup(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction( session -> {
|
||||||
|
session.createQuery( "delete from SomeEntity" ).executeUpdate();
|
||||||
|
session.createQuery( "delete from SomeEntityWithFalsePositive" ).executeUpdate();
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "SomeEntity")
|
||||||
@Table(name = "SOME_ENTITY")
|
@Table(name = "SOME_ENTITY")
|
||||||
static class SomeEntity {
|
static class SomeEntity {
|
||||||
@Id
|
@Id
|
||||||
|
@ -88,4 +124,53 @@ public class InvalidPropertyNameTest {
|
||||||
this.property = property;
|
this.property = property;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Entity(name = "SomeEntityWithFalsePositive")
|
||||||
|
static class SomeEntityWithFalsePositive {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String property1;
|
||||||
|
|
||||||
|
private String property2;
|
||||||
|
|
||||||
|
public SomeEntityWithFalsePositive() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public SomeEntityWithFalsePositive(Long id, String property1, String property2) {
|
||||||
|
this.id = id;
|
||||||
|
this.property1 = property1;
|
||||||
|
this.property2 = property2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Id
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProperty1() {
|
||||||
|
return property1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProperty1(String property1) {
|
||||||
|
this.property1 = property1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProperty2() {
|
||||||
|
return property2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProperty2(String property2) {
|
||||||
|
this.property2 = property2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transient
|
||||||
|
public String getProperty() {
|
||||||
|
return property1 + " " + property2;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue