Skip to content

Commit fb35dbf

Browse files
committed
HHH-18832 Don't skip bytecode enhancement just because an entity has a @Transient getter
1 parent 019cbf5 commit fb35dbf

File tree

2 files changed

+97
-4
lines changed

2 files changed

+97
-4
lines changed

hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/EnhancerImpl.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,11 @@ else if (methodName.startsWith("get") ||
446446
// convert field letter to lower case
447447
methodFieldName = methodFieldName.substring(0, 1).toLowerCase() + methodFieldName.substring(1);
448448
TypeList typeList = methodDescription.getDeclaredAnnotations().asTypeList();
449+
if (typeList.stream().anyMatch(typeDefinitions ->
450+
(typeDefinitions.getName().equals("jakarta.persistence.Transient")))) {
451+
// transient property so ignore it
452+
continue;
453+
}
449454
if (typeList.stream().anyMatch(typeDefinitions ->
450455
(typeDefinitions.getName().contains("jakarta.persistence")))) {
451456
propertyHasAnnotation = true;

hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/access/InvalidPropertyNameTest.java

Lines changed: 92 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,19 @@
44
*/
55
package org.hibernate.orm.test.bytecode.enhancement.access;
66

7-
import jakarta.persistence.*;
7+
import jakarta.persistence.Access;
8+
import jakarta.persistence.AccessType;
9+
import jakarta.persistence.Basic;
10+
import jakarta.persistence.Entity;
11+
import jakarta.persistence.Id;
12+
import jakarta.persistence.Table;
13+
import jakarta.persistence.Transient;
814
import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced;
9-
import org.hibernate.testing.orm.junit.*;
15+
import org.hibernate.testing.orm.junit.DomainModel;
16+
import org.hibernate.testing.orm.junit.FailureExpected;
17+
import org.hibernate.testing.orm.junit.JiraKey;
18+
import org.hibernate.testing.orm.junit.SessionFactory;
19+
import org.hibernate.testing.orm.junit.SessionFactoryScope;
1020
import org.junit.jupiter.api.AfterEach;
1121
import org.junit.jupiter.api.Test;
1222

@@ -15,16 +25,17 @@
1525
@DomainModel(
1626
annotatedClasses = {
1727
InvalidPropertyNameTest.SomeEntity.class,
28+
InvalidPropertyNameTest.SomeEntityWithFalsePositive.class
1829
}
1930
)
2031
@SessionFactory
21-
@JiraKey("HHH-16572")
2232
@BytecodeEnhanced
2333
public class InvalidPropertyNameTest {
2434

2535

2636
@Test
2737
@FailureExpected(jiraKey = "HHH-16572")
38+
@JiraKey("HHH-16572")
2839
public void test(SessionFactoryScope scope) {
2940
scope.inTransaction( session -> {
3041
session.persist( new SomeEntity( 1L, "field", "property" ) );
@@ -43,12 +54,40 @@ public void test(SessionFactoryScope scope) {
4354
} );
4455
}
4556

57+
@Test
58+
@JiraKey("HHH-18832")
59+
public void testNoFalsePositive(SessionFactoryScope scope) {
60+
scope.inTransaction( session -> {
61+
session.persist( new SomeEntityWithFalsePositive( 1L, "property1-initial", "property2-initial" ) );
62+
} );
63+
64+
// Before HHH-18832 was fixed, lazy-loading enhancement was (incorrectly) skipped,
65+
// resulting at best in `property1` being null in the code below,
66+
// 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()'
67+
// (see https://hibernate.zulipchat.com/#narrow/channel/132094-hibernate-orm-dev/topic/HHH-16572/near/481330806)
68+
scope.inTransaction( session -> {
69+
SomeEntityWithFalsePositive entity = session.getReference( SomeEntityWithFalsePositive.class, 1L );
70+
// Lazy-loading triggered by field access
71+
// Proves bytecode enhancement is effective
72+
assertThat( entity.property1 ).isEqualTo( "property1-initial" );
73+
} );
74+
75+
scope.inTransaction( session -> {
76+
SomeEntityWithFalsePositive entity = session.getReference( SomeEntityWithFalsePositive.class, 1L );
77+
// Proves bytecode enhancement is effective even for the transient method
78+
assertThat( entity.getProperty() ).isEqualTo( "property1-initial property2-initial" );
79+
} );
80+
}
81+
4682
@AfterEach
4783
public void cleanup(SessionFactoryScope scope) {
4884
// uncomment the following when @FailureExpected is removed above
4985
// scope.inTransaction( session -> {
5086
// session.remove( session.get( SomeEntity.class, 1L ) );
51-
// PropertyAccessTest} );
87+
// } );
88+
scope.inTransaction( session -> {
89+
session.remove( session.get( SomeEntityWithFalsePositive.class, 1L ) );
90+
} );
5291
}
5392

5493
@Entity
@@ -88,4 +127,53 @@ public void setPropertyMethod(String property) {
88127
this.property = property;
89128
}
90129
}
130+
131+
@Entity
132+
static class SomeEntityWithFalsePositive {
133+
134+
private Long id;
135+
136+
private String property1;
137+
138+
private String property2;
139+
140+
public SomeEntityWithFalsePositive() {
141+
}
142+
143+
public SomeEntityWithFalsePositive(Long id, String property1, String property2) {
144+
this.id = id;
145+
this.property1 = property1;
146+
this.property2 = property2;
147+
}
148+
149+
@Id
150+
public long getId() {
151+
return id;
152+
}
153+
154+
public void setId(long id) {
155+
this.id = id;
156+
}
157+
158+
public String getProperty1() {
159+
return property1;
160+
}
161+
162+
public void setProperty1(String property1) {
163+
this.property1 = property1;
164+
}
165+
166+
public String getProperty2() {
167+
return property2;
168+
}
169+
170+
public void setProperty2(String property2) {
171+
this.property2 = property2;
172+
}
173+
174+
@Transient
175+
public String getProperty() {
176+
return property1 + " " + property2;
177+
}
178+
}
91179
}

0 commit comments

Comments
 (0)