44 */
55package 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 ;
814import 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 ;
1020import org .junit .jupiter .api .AfterEach ;
1121import org .junit .jupiter .api .Test ;
1222
1525@ DomainModel (
1626 annotatedClasses = {
1727 InvalidPropertyNameTest .SomeEntity .class ,
28+ InvalidPropertyNameTest .SomeEntityWithFalsePositive .class
1829 }
1930)
2031@ SessionFactory
21- @ JiraKey ("HHH-16572" )
2232@ BytecodeEnhanced
2333public 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,15 +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 ) {
48- // uncomment the following when @FailureExpected is removed above
49- // scope.inTransaction( session -> {
50- // session.remove( session.get( SomeEntity.class, 1L ) );
51- // PropertyAccessTest } );
84+ scope . inTransaction ( session -> {
85+ session . createQuery ( "delete from SomeEntity" ). executeUpdate ();
86+ session .createQuery ( "delete from SomeEntityWithFalsePositive" ). executeUpdate ( );
87+ } );
5288 }
5389
54- @ Entity
90+ @ Entity ( name = "SomeEntity" )
5591 @ Table (name = "SOME_ENTITY" )
5692 static class SomeEntity {
5793 @ Id
@@ -88,4 +124,53 @@ public void setPropertyMethod(String property) {
88124 this .property = property ;
89125 }
90126 }
127+
128+ @ Entity (name = "SomeEntityWithFalsePositive" )
129+ static class SomeEntityWithFalsePositive {
130+
131+ private Long id ;
132+
133+ private String property1 ;
134+
135+ private String property2 ;
136+
137+ public SomeEntityWithFalsePositive () {
138+ }
139+
140+ public SomeEntityWithFalsePositive (Long id , String property1 , String property2 ) {
141+ this .id = id ;
142+ this .property1 = property1 ;
143+ this .property2 = property2 ;
144+ }
145+
146+ @ Id
147+ public long getId () {
148+ return id ;
149+ }
150+
151+ public void setId (long id ) {
152+ this .id = id ;
153+ }
154+
155+ public String getProperty1 () {
156+ return property1 ;
157+ }
158+
159+ public void setProperty1 (String property1 ) {
160+ this .property1 = property1 ;
161+ }
162+
163+ public String getProperty2 () {
164+ return property2 ;
165+ }
166+
167+ public void setProperty2 (String property2 ) {
168+ this .property2 = property2 ;
169+ }
170+
171+ @ Transient
172+ public String getProperty () {
173+ return property1 + " " + property2 ;
174+ }
175+ }
91176}
0 commit comments