Skip to content

Commit ed185b9

Browse files
committed
HHH-10017 - bytecode enhancement - consistent handling of persistent attributes, regardeless of access type
1 parent 603a410 commit ed185b9

14 files changed

+686
-195
lines changed

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

Lines changed: 17 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,13 @@ public String buildInLineDirtyCheckingBodyFragment(EnhancementContext context, C
3434
final StringBuilder builder = new StringBuilder();
3535
try {
3636
// should ignore primary keys
37-
for ( Object o : currentValue.getType().getAnnotations() ) {
38-
if ( o instanceof Id) {
39-
return "";
40-
}
37+
if (PersistentAttributesHelper.hasAnnotation( currentValue, Id.class ) ) {
38+
return "";
4139
}
4240

4341
// primitives || enums
4442
if ( currentValue.getType().isPrimitive() || currentValue.getType().isEnum() ) {
45-
builder.append( String.format( "if (%s != $1)", currentValue.getName() ) );
43+
builder.append( String.format( " if (%s != $1)", currentValue.getName() ) );
4644
}
4745
// simple data types
4846
else if ( currentValue.getType().getName().startsWith( "java.lang" )
@@ -51,7 +49,7 @@ else if ( currentValue.getType().getName().startsWith( "java.lang" )
5149
|| currentValue.getType().getName().startsWith( "java.sql.Date" )
5250
|| currentValue.getType().getName().startsWith( "java.util.Date" )
5351
|| currentValue.getType().getName().startsWith( "java.util.Calendar" ) ) {
54-
builder.append( String.format( "if (%s == null || !%<s.equals($1))", currentValue.getName() ) );
52+
builder.append( String.format( " if (%s == null || !%<s.equals($1))", currentValue.getName() ) );
5553
}
5654
// all other objects
5755
else {
@@ -64,15 +62,12 @@ else if ( currentValue.getType().getName().startsWith( "java.lang" )
6462
}
6563
}
6664
}
67-
builder.append( String.format( "if (%1$s == null || !%2$s.equals(%1$s, $1))",
65+
builder.append( String.format( " if (%1$s == null || !%2$s.equals(%1$s, $1))",
6866
currentValue.getName(),
6967
EqualsHelper.class.getName() ) );
7068
}
7169
builder.append( String.format( " { %s(\"%s\"); }", EnhancerConstants.TRACKER_CHANGER_NAME, currentValue.getName() ) );
7270
}
73-
catch (ClassNotFoundException e) {
74-
e.printStackTrace();
75-
}
7671
catch (NotFoundException e) {
7772
e.printStackTrace();
7873
}
@@ -128,22 +123,18 @@ private ObjectAttributeTypeDescriptor(CtClass concreteType) {
128123
}
129124

130125
public String buildReadInterceptionBodyFragment(String fieldName) {
131-
return String.format( "" +
132-
"if ( %3$s() != null ) {%n" +
133-
" this.%1$s = (%2$s) %3$s().readObject(this, \"%1$s\", this.%1$s);%n" +
134-
"}",
126+
return String.format(
127+
" if ( %3$s() != null ) { this.%1$s = (%2$s) %3$s().readObject(this, \"%1$s\", this.%1$s); }%n",
135128
fieldName,
136129
type,
137130
EnhancerConstants.INTERCEPTOR_GETTER_NAME );
138131
}
139132

140133
public String buildWriteInterceptionBodyFragment(String fieldName) {
141-
return String.format( "" +
142-
"%2$s localVar = $1;%n" +
143-
"if ( %3$s() != null ) {%n" +
144-
" localVar = (%2$s) %3$s().writeObject(this, \"%1$s\", this.%1$s, $1);%n" +
145-
"}%n" +
146-
"this.%1$s = localVar;",
134+
return String.format(
135+
" %2$s localVar = $1;%n" +
136+
" if ( %3$s() != null ) { localVar = (%2$s) %3$s().writeObject(this, \"%1$s\", this.%1$s, $1); }%n" +
137+
" this.%1$s = localVar;",
147138
fieldName,
148139
type,
149140
EnhancerConstants.INTERCEPTOR_GETTER_NAME );
@@ -166,22 +157,18 @@ private PrimitiveAttributeTypeDescriptor(Class<?> primitiveType) {
166157
}
167158

168159
public String buildReadInterceptionBodyFragment(String fieldName) {
169-
return String.format( "" +
170-
"if (%3$s() != null ) {%n" +
171-
" this.%1$s = %3$s().read%2$s(this, \"%1$s\", this.%1$s);%n" +
172-
"}",
160+
return String.format(
161+
" if (%3$s() != null ) { this.%1$s = %3$s().read%2$s(this, \"%1$s\", this.%1$s); }",
173162
fieldName,
174163
type,
175164
EnhancerConstants.INTERCEPTOR_GETTER_NAME );
176165
}
177166

178167
public String buildWriteInterceptionBodyFragment(String fieldName) {
179-
return String.format( "" +
180-
"%2$s localVar = $1;%n" +
181-
"if ( %4$s() != null ) {%n" +
182-
" localVar = %4$s().write%3$s(this, \"%1$s\", this.%1$s, $1);%n" +
183-
"}%n" +
184-
"this.%1$s = localVar;",
168+
return String.format(
169+
" %2$s localVar = $1;%n" +
170+
" if ( %4$s() != null ) { localVar = %4$s().write%3$s(this, \"%1$s\", this.%1$s, $1); }%n" +
171+
" this.%1$s = localVar;",
185172
fieldName,
186173
type.toLowerCase( Locale.ROOT ),
187174
type,

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

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,16 @@
1717
import javassist.Modifier;
1818
import javassist.NotFoundException;
1919

20-
import org.hibernate.bytecode.enhance.internal.tracker.CollectionTracker;
2120
import org.hibernate.bytecode.enhance.internal.tracker.DirtyTracker;
21+
import org.hibernate.bytecode.enhance.internal.tracker.SimpleCollectionTracker;
2222
import org.hibernate.bytecode.enhance.internal.tracker.SimpleFieldTracker;
23+
import org.hibernate.bytecode.enhance.spi.CollectionTracker;
2324
import org.hibernate.bytecode.enhance.spi.EnhancementContext;
2425
import org.hibernate.bytecode.enhance.spi.EnhancementException;
2526
import org.hibernate.bytecode.enhance.spi.Enhancer;
2627
import org.hibernate.bytecode.enhance.spi.EnhancerConstants;
28+
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoader;
29+
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
2730
import org.hibernate.engine.spi.SelfDirtinessTracker;
2831

2932
/**
@@ -39,6 +42,7 @@ public EntityEnhancer(EnhancementContext context) {
3942

4043
// assuming the number of fields is not very high, SimpleFieldTracker implementation it's the fastest
4144
private static final String DIRTY_TRACKER_IMPL = SimpleFieldTracker.class.getName();
45+
private static final String COLLECTION_TRACKER_IMPL = SimpleCollectionTracker.class.getName();
4246

4347
public void enhance(CtClass managedCtClass) {
4448
// add the ManagedEntity interface
@@ -110,7 +114,7 @@ private void addInLineDirtyHandling(CtClass managedCtClass) {
110114

111115
FieldWriter.addField(
112116
managedCtClass,
113-
classPool.get( DIRTY_TRACKER_IMPL ),
117+
classPool.get( DirtyTracker.class.getName() ),
114118
EnhancerConstants.TRACKER_FIELD_NAME
115119
);
116120
FieldWriter.addField(
@@ -181,6 +185,24 @@ private void createDirtyTrackerMethods(CtClass managedCtClass) {
181185
EnhancerConstants.TRACKER_FIELD_NAME,
182186
EnhancerConstants.TRACKER_COLLECTION_CLEAR_NAME
183187
);
188+
189+
MethodWriter.write(
190+
managedCtClass,
191+
"public void %1$s(boolean f) {%n" +
192+
" if (%2$s == null) %2$s = new %3$s();%n %2$s.suspend(f);%n" +
193+
"}",
194+
EnhancerConstants.TRACKER_SUSPEND_NAME,
195+
EnhancerConstants.TRACKER_FIELD_NAME ,
196+
DIRTY_TRACKER_IMPL
197+
);
198+
199+
MethodWriter.write(
200+
managedCtClass,
201+
"public %s %s() { return %s; }",
202+
CollectionTracker.class.getName(),
203+
EnhancerConstants.TRACKER_COLLECTION_GET_NAME,
204+
EnhancerConstants.TRACKER_COLLECTION_NAME
205+
);
184206
}
185207
catch (CannotCompileException cce) {
186208
cce.printStackTrace();
@@ -197,7 +219,7 @@ private List<CtField> collectCollectionFields(CtClass managedCtClass) {
197219
}
198220
if ( enhancementContext.isPersistentField( ctField ) ) {
199221
for ( CtClass ctClass : ctField.getType().getInterfaces() ) {
200-
if ( ctClass.getName().equals( Collection.class.getName() ) ) {
222+
if ( PersistentAttributesHelper.isAssignable( ctClass, Collection.class.getName() ) ) {
201223
collectionList.add( ctField );
202224
break;
203225
}
@@ -217,9 +239,7 @@ private void createCollectionDirtyCheckMethod(CtClass managedCtClass) {
217239
body.append(
218240
String.format(
219241
"private boolean %1$s() {%n" +
220-
" if (%2$s == null) {%n" +
221-
" return false;%n" +
222-
" }%n",
242+
" if (%2$s == null) { return false; }%n%n",
223243
EnhancerConstants.TRACKER_COLLECTION_CHANGED_NAME,
224244
EnhancerConstants.TRACKER_COLLECTION_NAME
225245
)
@@ -231,7 +251,7 @@ private void createCollectionDirtyCheckMethod(CtClass managedCtClass) {
231251
String.format(
232252
" // collection field [%1$s]%n" +
233253
" if (%1$s == null && %2$s.getSize(\"%1$s\") != -1) { return true; }%n" +
234-
" if (%1$s != null && %2$s.getSize(\"%1$s\") != %1$s.size()) { return true; }%n",
254+
" if (%1$s != null && %2$s.getSize(\"%1$s\") != %1$s.size()) { return true; }%n%n",
235255
ctField.getName(),
236256
EnhancerConstants.TRACKER_COLLECTION_NAME
237257
)
@@ -254,7 +274,7 @@ private void createCollectionDirtyCheckGetFieldsMethod(CtClass managedCtClass) {
254274
body.append(
255275
String.format(
256276
"private void %1$s(%3$s tracker) {%n" +
257-
" if (%2$s == null) { return; }%n",
277+
" if (%2$s == null) { return; }%n%n",
258278
EnhancerConstants.TRACKER_COLLECTION_CHANGED_FIELD_NAME,
259279
EnhancerConstants.TRACKER_COLLECTION_NAME,
260280
DirtyTracker.class.getName()
@@ -267,7 +287,7 @@ private void createCollectionDirtyCheckGetFieldsMethod(CtClass managedCtClass) {
267287
String.format(
268288
" // Collection field [%1$s]%n" +
269289
" if (%1$s == null && %2$s.getSize(\"%1$s\") != -1) { tracker.add(\"%1$s\"); }%n" +
270-
" if (%1$s != null && %2$s.getSize(\"%1$s\") != %1$s.size()) { tracker.add(\"%1$s\"); }%n",
290+
" if (%1$s != null && %2$s.getSize(\"%1$s\") != %1$s.size()) { tracker.add(\"%1$s\"); }%n%n",
271291
ctField.getName(),
272292
EnhancerConstants.TRACKER_COLLECTION_NAME
273293
)
@@ -289,21 +309,35 @@ private void createClearDirtyCollectionMethod(CtClass managedCtClass) throws Can
289309

290310
body.append(
291311
String.format(
292-
"private void %1$s() {%n" +
293-
" if (%2$s == null) { %2$s = new %3$s(); }%n",
312+
"private void %1$s() {%n" +
313+
" if (%2$s == null) { %2$s = new %3$s(); }%n" +
314+
" %4$s lazyInterceptor = null;%n",
294315
EnhancerConstants.TRACKER_COLLECTION_CLEAR_NAME,
295316
EnhancerConstants.TRACKER_COLLECTION_NAME,
296-
CollectionTracker.class.getName()
317+
COLLECTION_TRACKER_IMPL,
318+
LazyAttributeLoader.class.getName()
297319
)
298320
);
299321

322+
if ( PersistentAttributesHelper.isAssignable( managedCtClass, PersistentAttributeInterceptable.class.getName() ) ) {
323+
body.append(
324+
String.format(
325+
" if(%1$s != null && %1$s instanceof %2$s) lazyInterceptor = (%2$s) %1$s;%n%n",
326+
EnhancerConstants.INTERCEPTOR_FIELD_NAME,
327+
LazyAttributeLoader.class.getName()
328+
)
329+
);
330+
}
331+
300332
for ( CtField ctField : collectCollectionFields( managedCtClass ) ) {
301333
if ( !enhancementContext.isMappedCollection( ctField ) ) {
302334
body.append(
303335
String.format(
304-
" // Collection field [%1$s]%n" +
305-
" if (%1$s == null) { %2$s.add(\"%1$s\", -1); }%n" +
306-
" else { %2$s.add(\"%1$s\", %1$s.size()); }%n",
336+
" // collection field [%1$s]%n" +
337+
" if (lazyInterceptor == null || lazyInterceptor.isAttributeLoaded(\"%1$s\")) {%n" +
338+
" if (%1$s == null) { %2$s.add(\"%1$s\", -1); }%n" +
339+
" else { %2$s.add(\"%1$s\", %1$s.size()); }%n" +
340+
" }%n%n",
307341
ctField.getName(),
308342
EnhancerConstants.TRACKER_COLLECTION_NAME
309343
)

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,20 @@
66
*/
77
package org.hibernate.bytecode.enhance.internal;
88

9+
import javax.persistence.Transient;
10+
911
import javassist.CannotCompileException;
1012
import javassist.CtClass;
1113
import javassist.CtField;
1214
import javassist.Modifier;
1315
import javassist.bytecode.AnnotationsAttribute;
1416
import javassist.bytecode.FieldInfo;
1517
import javassist.bytecode.annotation.Annotation;
18+
1619
import org.hibernate.bytecode.enhance.spi.EnhancementException;
1720
import org.hibernate.internal.CoreLogging;
1821
import org.hibernate.internal.CoreMessageLogger;
1922

20-
import javax.persistence.Transient;
21-
2223
/**
2324
* @author <a href="mailto:[email protected]">Luis Barreiro</a>
2425
*/
@@ -50,7 +51,7 @@ public static void addFieldWithGetterAndSetter(CtClass target, CtClass type, Str
5051

5152
private static void addPrivateTransient(CtClass target, CtClass type, String name) {
5253
addWithModifiers( target, type, name, Modifier.PRIVATE | Modifier.TRANSIENT, Transient.class );
53-
log.debugf( "Wrote field into [%s]: @Transient private transient %s %s;%n", target.getName(), type.getName(), name );
54+
log.debugf( "Wrote field into [%s]: @Transient private transient %s %s;", target.getName(), type.getName(), name );
5455
}
5556

5657
private static void addWithModifiers(CtClass target, CtClass type, String name, int modifiers, Class<?> ... annotations ) {

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ private MethodWriter() { }
3737
public static CtMethod write(CtClass target, String format, Object ... args) throws CannotCompileException {
3838
final String body = String.format( format, args );
3939
// System.out.printf( "writing method into [%s]:%n%s%n", target.getName(), body );
40-
log.debugf( "writing method into [%s]:%n%s%n", target.getName(), body );
40+
log.debugf( "writing method into [%s]:%n%s", target.getName(), body );
4141
final CtMethod method = CtNewMethod.make( body, target );
4242
target.addMethod( method );
4343
return method;
@@ -47,7 +47,7 @@ public static CtMethod write(CtClass target, String format, Object ... args) thr
4747

4848
public static CtMethod addGetter(CtClass target, String field, String name) {
4949
try {
50-
log.debugf( "Writing getter method [%s] into [%s] for field [%s]%n", name, target.getName(), field );
50+
log.debugf( "Writing getter method [%s] into [%s] for field [%s]", name, target.getName(), field );
5151
final CtMethod method = CtNewMethod.getter( name, target.getField( field ) );
5252
target.addMethod( method );
5353
return method;
@@ -64,7 +64,7 @@ public static CtMethod addGetter(CtClass target, String field, String name) {
6464

6565
public static CtMethod addSetter(CtClass target, String field, String name) {
6666
try {
67-
log.debugf( "Writing setter method [%s] into [%s] for field [%s]%n", name, target.getName(), field );
67+
log.debugf( "Writing setter method [%s] into [%s] for field [%s]", name, target.getName(), field );
6868
final CtMethod method = CtNewMethod.setter( name, target.getField( field ) );
6969
target.addMethod( method );
7070
return method;

0 commit comments

Comments
 (0)