99import jakarta .persistence .Basic ;
1010import jakarta .persistence .Entity ;
1111import jakarta .persistence .Id ;
12- import jakarta .persistence .Table ;
12+ import jakarta .persistence .PostLoad ;
13+ import jakarta .persistence .PrePersist ;
14+ import jakarta .persistence .Transient ;
15+
1316import org .hibernate .bytecode .enhance .internal .bytebuddy .EnhancerImpl ;
1417import org .hibernate .bytecode .enhance .spi .EnhancementContext ;
1518import org .hibernate .bytecode .enhance .spi .EnhancementException ;
1821import org .hibernate .bytecode .internal .bytebuddy .ByteBuddyState ;
1922import org .hibernate .bytecode .spi .ByteCodeHelper ;
2023import org .hibernate .testing .bytecode .enhancement .EnhancerTestContext ;
24+ import org .hibernate .testing .orm .junit .Jira ;
2125import org .hibernate .testing .orm .junit .JiraKey ;
2226import org .junit .jupiter .api .Test ;
2327
2428import java .io .IOException ;
2529import java .io .InputStream ;
30+ import java .util .UUID ;
2631
2732import static org .assertj .core .api .Assertions .assertThat ;
2833import static org .assertj .core .api .Assertions .assertThatThrownBy ;
@@ -39,28 +44,31 @@ public UnsupportedEnhancementStrategy getUnsupportedEnhancementStrategy() {
3944 return UnsupportedEnhancementStrategy .SKIP ;
4045 }
4146 };
42- byte [] originalBytes = getAsBytes ( SomeEntity .class );
43- byte [] enhancedBytes = doEnhance ( SomeEntity .class , originalBytes , context );
47+ byte [] enhancedBytes = doEnhance ( SomeEntity .class , context );
4448 assertThat ( enhancedBytes ).isNull (); // null means "not enhanced"
4549 }
4650
4751 @ Test
4852 public void fail () throws IOException {
49- var context = new EnhancerTestContext () {
50- @ Override
51- public UnsupportedEnhancementStrategy getUnsupportedEnhancementStrategy () {
52- return UnsupportedEnhancementStrategy .FAIL ;
53- }
54- };
55- byte [] originalBytes = getAsBytes ( SomeEntity .class );
56- assertThatThrownBy ( () -> doEnhance ( SomeEntity .class , originalBytes , context ) )
57- .isInstanceOf ( EnhancementException .class )
53+ var context = new UnsupportedEnhancerContext ();
54+ assertThatThrownBy ( () -> doEnhance ( SomeEntity .class , context ) ).isInstanceOf ( EnhancementException .class )
5855 .hasMessageContainingAll (
5956 String .format (
6057 "Enhancement of [%s] failed because no field named [%s] could be found for property accessor method [%s]." ,
61- SomeEntity .class .getName (), "propertyMethod" , "getPropertyMethod" ),
62- "To fix this, make sure all property accessor methods have a matching field."
58+ SomeEntity .class .getName (),
59+ "propertyMethod" ,
60+ "getPropertyMethod"
61+ ), "To fix this, make sure all property accessor methods have a matching field."
6362 );
63+ assertThatThrownBy ( () -> doEnhance ( SomeOtherEntity .class , context ) ).isInstanceOf ( EnhancementException .class )
64+ .hasMessageContainingAll (
65+ String .format (
66+ "Enhancement of [%s] failed because no field named [%s] could be found for property accessor method [%s]." ,
67+ SomeOtherEntity .class .getName (),
68+ "propertyMethod" ,
69+ "setPropertyMethod"
70+ ), "To fix this, make sure all property accessor methods have a matching field."
71+ );
6472 }
6573
6674 @ Test
@@ -73,26 +81,49 @@ public UnsupportedEnhancementStrategy getUnsupportedEnhancementStrategy() {
7381 return UnsupportedEnhancementStrategy .LEGACY ;
7482 }
7583 };
76- byte [] originalBytes = getAsBytes ( SomeEntity .class );
77- byte [] enhancedBytes = doEnhance ( SomeEntity .class , originalBytes , context );
84+ byte [] enhancedBytes = doEnhance ( SomeEntity .class , context );
7885 assertThat ( enhancedBytes ).isNotNull (); // non-null means enhancement _was_ performed
7986 }
8087
81- private byte [] doEnhance (Class <SomeEntity > someEntityClass , byte [] originalBytes , EnhancementContext context ) {
88+ @ Test
89+ @ Jira ( "https://hibernate.atlassian.net/browse/HHH-18903" )
90+ @ Jira ( "https://hibernate.atlassian.net/browse/HHH-18904" )
91+ public void testEntityListeners () throws IOException {
92+ // non-null means check passed and enhancement _was_ performed
93+ assertThat ( doEnhance ( EventListenersEntity .class , new UnsupportedEnhancerContext () ) ).isNotNull ();
94+ }
95+
96+ @ Test
97+ @ Jira ( "https://hibernate.atlassian.net/browse/HHH-18903" )
98+ @ Jira ( "https://hibernate.atlassian.net/browse/HHH-18904" )
99+ public void testAccessTypeFieldEntity () throws IOException {
100+ var context = new UnsupportedEnhancerContext ();
101+ // non-null means check passed and enhancement _was_ performed
102+ assertThat ( doEnhance ( ExplicitAccessTypeFieldEntity .class , context ) ).isNotNull ();
103+ assertThat ( doEnhance ( ImplicitAccessTypeFieldEntity .class , context ) ).isNotNull ();
104+ }
105+
106+ private static byte [] doEnhance (Class <?> entityClass , EnhancementContext context ) throws IOException {
82107 final ByteBuddyState byteBuddyState = new ByteBuddyState ();
83108 final Enhancer enhancer = new EnhancerImpl ( context , byteBuddyState );
84- return enhancer .enhance ( someEntityClass .getName (), originalBytes );
109+ return enhancer .enhance ( entityClass .getName (), getAsBytes ( entityClass ) );
85110 }
86111
87- private byte [] getAsBytes (Class <?> clazz ) throws IOException {
112+ private static byte [] getAsBytes (Class <?> clazz ) throws IOException {
88113 final String classFile = clazz .getName ().replace ( '.' , '/' ) + ".class" ;
89114 try (InputStream classFileStream = clazz .getClassLoader ().getResourceAsStream ( classFile )) {
90115 return ByteCodeHelper .readByteCode ( classFileStream );
91116 }
92117 }
93118
94- @ Entity
95- @ Table (name = "SOME_ENTITY" )
119+ static class UnsupportedEnhancerContext extends EnhancerTestContext {
120+ @ Override
121+ public UnsupportedEnhancementStrategy getUnsupportedEnhancementStrategy () {
122+ return UnsupportedEnhancementStrategy .FAIL ;
123+ }
124+ }
125+
126+ @ Entity (name = "SomeEntity" )
96127 static class SomeEntity {
97128 @ Id
98129 Long id ;
@@ -102,15 +133,6 @@ static class SomeEntity {
102133
103134 String property ;
104135
105- public SomeEntity () {
106- }
107-
108- public SomeEntity (Long id , String field , String property ) {
109- this .id = id ;
110- this .field = field ;
111- this .property = property ;
112- }
113-
114136 /**
115137 * The following property accessor methods are purposely named incorrectly to
116138 * not match the "property" field. The HHH-16572 change ensures that
@@ -128,4 +150,105 @@ public void setPropertyMethod(String property) {
128150 this .property = property ;
129151 }
130152 }
153+
154+ @ Entity (name = "SomeOtherEntity" )
155+ static class SomeOtherEntity {
156+ @ Id
157+ Long id ;
158+
159+ @ Basic
160+ String field ;
161+
162+ String property ;
163+ @ Access (AccessType .PROPERTY )
164+ public void setPropertyMethod (String property ) {
165+ this .property = property ;
166+ }
167+ }
168+
169+ @ Entity (name = "EventListenersEntity" )
170+ static class EventListenersEntity {
171+ private UUID id ;
172+
173+ private String status = "new" ;
174+
175+ @ Id
176+ public UUID getId () {
177+ return id ;
178+ }
179+
180+ public void setId (UUID id ) {
181+ this .id = id ;
182+ }
183+
184+ // special case, we should let it through
185+ public UUID get () {
186+ return id ;
187+ }
188+
189+ @ PrePersist
190+ public void setId () {
191+ id = UUID .randomUUID ();
192+ }
193+
194+ @ Transient
195+ public String getState () {
196+ return status ;
197+ }
198+
199+ @ PostLoad
200+ public void setState () {
201+ status = "loaded" ;
202+ }
203+
204+ @ Transient
205+ public boolean isLoaded () {
206+ return status .equals ( "loaded" );
207+ }
208+ }
209+
210+ @ Entity (name = "ExplicitAccessTypeFieldEntity" )
211+ @ Access ( AccessType .FIELD )
212+ static class ExplicitAccessTypeFieldEntity {
213+ @ Id
214+ private Long id ;
215+
216+ public Long getId () {
217+ return id ;
218+ }
219+
220+ public void setId (Long id ) {
221+ this .id = id ;
222+ }
223+
224+ public Long get () {
225+ return id ;
226+ }
227+
228+ public String getSomething () {
229+ return "something" ;
230+ }
231+ }
232+
233+ @ Entity (name = "ImplicitAccessTypeFieldEntity" )
234+ static class ImplicitAccessTypeFieldEntity {
235+ @ Id
236+ private Long id ;
237+
238+ public Long getId () {
239+ return id ;
240+ }
241+
242+ public void setId (Long id ) {
243+ this .id = id ;
244+ }
245+
246+ public Long get () {
247+ return id ;
248+ }
249+
250+ public String getAnother () {
251+ return "another" ;
252+ }
253+ }
131254}
0 commit comments