Skip to content

Commit

Permalink
HHH-15634 Lazy basic property does not get updated on change: inline …
Browse files Browse the repository at this point in the history
…dirty checking, lazy basic properties are not upated when set to null
  • Loading branch information
dreab8 committed Oct 27, 2022
1 parent 98d3d2c commit 12d1e30
Show file tree
Hide file tree
Showing 2 changed files with 210 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.bytecode.enhance.internal.bytebuddy;

import java.util.Objects;

import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;

public final class InlineDirtyCheckerEqualsHelper {

public static boolean areEquals(
PersistentAttributeInterceptable persistentAttributeInterceptable,
String fieldName,
Object a,
Object b) {
final PersistentAttributeInterceptor persistentAttributeInterceptor = persistentAttributeInterceptable.$$_hibernate_getInterceptor();
if ( persistentAttributeInterceptor != null
&& !persistentAttributeInterceptor.getInitializedLazyAttributeNames().contains( fieldName ) ) {
return false;
}
return Objects.deepEquals( a, b );
}

public static boolean areEquals(
PersistentAttributeInterceptable persistentAttributeInterceptable,
String fieldName,
boolean a,
boolean b) {
final PersistentAttributeInterceptor persistentAttributeInterceptor = persistentAttributeInterceptable.$$_hibernate_getInterceptor();
if ( persistentAttributeInterceptor != null
&& !persistentAttributeInterceptor.getInitializedLazyAttributeNames().contains( fieldName ) ) {
return false;
}
return a == b;
}

public static boolean areEquals(
PersistentAttributeInterceptable persistentAttributeInterceptable,
String fieldName,
byte a,
byte b) {
final PersistentAttributeInterceptor persistentAttributeInterceptor = persistentAttributeInterceptable.$$_hibernate_getInterceptor();
if ( persistentAttributeInterceptor != null
&& !persistentAttributeInterceptor.getInitializedLazyAttributeNames().contains( fieldName ) ) {
return false;
}
return a == b;
}

public static boolean areEquals(
PersistentAttributeInterceptable persistentAttributeInterceptable,
String fieldName,
short a,
short b) {
final PersistentAttributeInterceptor persistentAttributeInterceptor = persistentAttributeInterceptable.$$_hibernate_getInterceptor();
if ( persistentAttributeInterceptor != null
&& !persistentAttributeInterceptor.getInitializedLazyAttributeNames().contains( fieldName ) ) {
return false;
}
return a == b;
}

public static boolean areEquals(
PersistentAttributeInterceptable persistentAttributeInterceptable,
String fieldName,
char a,
char b) {
final PersistentAttributeInterceptor persistentAttributeInterceptor = persistentAttributeInterceptable.$$_hibernate_getInterceptor();
if ( persistentAttributeInterceptor != null
&& !persistentAttributeInterceptor.getInitializedLazyAttributeNames().contains( fieldName ) ) {
return false;
}
return a == b;
}

public static boolean areEquals(
PersistentAttributeInterceptable persistentAttributeInterceptable,
String fieldName,
int a,
int b) {
final PersistentAttributeInterceptor persistentAttributeInterceptor = persistentAttributeInterceptable.$$_hibernate_getInterceptor();
if ( persistentAttributeInterceptor != null
&& !persistentAttributeInterceptor.getInitializedLazyAttributeNames().contains( fieldName ) ) {
return false;
}
return a == b;
}

public static boolean areEquals(
PersistentAttributeInterceptable persistentAttributeInterceptable,
String fieldName,
long a,
long b) {
final PersistentAttributeInterceptor persistentAttributeInterceptor = persistentAttributeInterceptable.$$_hibernate_getInterceptor();
if ( persistentAttributeInterceptor != null
&& !persistentAttributeInterceptor.getInitializedLazyAttributeNames().contains( fieldName ) ) {
return false;
}
return a == b;
}

public static boolean areEquals(
PersistentAttributeInterceptable persistentAttributeInterceptable,
String fieldName,
float a,
float b) {
final PersistentAttributeInterceptor persistentAttributeInterceptor = persistentAttributeInterceptable.$$_hibernate_getInterceptor();
if ( persistentAttributeInterceptor != null
&& !persistentAttributeInterceptor.getInitializedLazyAttributeNames().contains( fieldName ) ) {
return false;
}
return a == b;
}

public static boolean areEquals(
PersistentAttributeInterceptable persistentAttributeInterceptable,
String fieldName,
double a,
double b) {
final PersistentAttributeInterceptor persistentAttributeInterceptor = persistentAttributeInterceptable.$$_hibernate_getInterceptor();
if ( persistentAttributeInterceptor != null
&& !persistentAttributeInterceptor.getInitializedLazyAttributeNames().contains( fieldName ) ) {
return false;
}
return a == b;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import org.hibernate.bytecode.enhance.internal.bytebuddy.EnhancerImpl.AnnotatedFieldDescription;
import org.hibernate.bytecode.enhance.spi.EnhancerConstants;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;

import net.bytebuddy.ClassFileVersion;
import net.bytebuddy.asm.Advice;
Expand All @@ -36,11 +37,17 @@ final class InlineDirtyCheckingHandler implements Implementation, ByteCodeAppend
private final TypeDescription managedCtClass;

private final FieldDescription.InDefinedShape persistentField;
private final boolean applyLazyCheck;

private InlineDirtyCheckingHandler(Implementation delegate, TypeDescription managedCtClass, FieldDescription.InDefinedShape persistentField) {
private InlineDirtyCheckingHandler(
Implementation delegate,
TypeDescription managedCtClass,
FieldDescription.InDefinedShape persistentField,
boolean applyLazyCheck) {
this.delegate = delegate;
this.managedCtClass = managedCtClass;
this.persistentField = persistentField;
this.applyLazyCheck = applyLazyCheck;
}

static Implementation wrap(
Expand All @@ -57,8 +64,12 @@ else if ( !persistentField.hasAnnotation( Id.class )
&& !persistentField.hasAnnotation( EmbeddedId.class )
&& !( persistentField.getType().asErasure().isAssignableTo( Collection.class )
&& enhancementContext.isMappedCollection( persistentField ) ) ) {
implementation = new InlineDirtyCheckingHandler( implementation, managedCtClass,
persistentField.asDefined() );
implementation = new InlineDirtyCheckingHandler(
implementation,
managedCtClass,
persistentField.asDefined(),
enhancementContext.hasLazyLoadableAttributes( managedCtClass )
);
}

if ( enhancementContext.isCompositeClass( persistentField.getType().asErasure() )
Expand Down Expand Up @@ -99,6 +110,11 @@ public Size apply(
Context implementationContext,
MethodDescription instrumentedMethod) {
// if (arg != field) {

if ( applyLazyCheck ) {
methodVisitor.visitVarInsn( Opcodes.ALOAD, 0 );
methodVisitor.visitLdcInsn( persistentField.getName() );
}
methodVisitor.visitVarInsn( Type.getType( persistentField.getType().asErasure().getDescriptor() ).getOpcode( Opcodes.ILOAD ), 1 );
methodVisitor.visitVarInsn( Opcodes.ALOAD, 0 );
if ( persistentField.getDeclaringType().asErasure().equals( managedCtClass ) ) {
Expand All @@ -119,30 +135,69 @@ public Size apply(
);
}
int branchCode;
if ( persistentField.getType().isPrimitive() ) {
if ( persistentField.getType().represents( long.class ) ) {
methodVisitor.visitInsn( Opcodes.LCMP );
}
else if ( persistentField.getType().represents( float.class ) ) {
methodVisitor.visitInsn( Opcodes.FCMPL );
}
else if ( persistentField.getType().represents( double.class ) ) {
methodVisitor.visitInsn( Opcodes.DCMPL );
if ( applyLazyCheck ) {
if ( persistentField.getType().isPrimitive() ) {
methodVisitor.visitMethodInsn(
Opcodes.INVOKESTATIC,
Type.getInternalName( InlineDirtyCheckerEqualsHelper.class ),
"areEquals",
Type.getMethodDescriptor(
Type.getType( boolean.class ),
Type.getType( PersistentAttributeInterceptable.class ),
Type.getType( String.class ),
Type.getType( persistentField.getDescriptor() ),
Type.getType( persistentField.getDescriptor() )
),
false
);
}
else {
methodVisitor.visitInsn( Opcodes.ISUB );
methodVisitor.visitMethodInsn(
Opcodes.INVOKESTATIC,
Type.getInternalName( InlineDirtyCheckerEqualsHelper.class ),
"areEquals",
Type.getMethodDescriptor(
Type.getType( boolean.class ),
Type.getType( PersistentAttributeInterceptable.class ),
Type.getType( String.class ),
Type.getType( Object.class ),
Type.getType( Object.class )
),
false
);
}
branchCode = Opcodes.IFEQ;
branchCode = Opcodes.IFNE;
}
else {
methodVisitor.visitMethodInsn(
Opcodes.INVOKESTATIC,
Type.getInternalName( Objects.class ),
"deepEquals",
Type.getMethodDescriptor( Type.getType( boolean.class ), Type.getType( Object.class ), Type.getType( Object.class ) ),
false
);
branchCode = Opcodes.IFNE;
if ( persistentField.getType().isPrimitive() ) {
if ( persistentField.getType().represents( long.class ) ) {
methodVisitor.visitInsn( Opcodes.LCMP );
}
else if ( persistentField.getType().represents( float.class ) ) {
methodVisitor.visitInsn( Opcodes.FCMPL );
}
else if ( persistentField.getType().represents( double.class ) ) {
methodVisitor.visitInsn( Opcodes.DCMPL );
}
else {
methodVisitor.visitInsn( Opcodes.ISUB );
}
branchCode = Opcodes.IFEQ;
}
else {
methodVisitor.visitMethodInsn(
Opcodes.INVOKESTATIC,
Type.getInternalName( Objects.class ),
"deepEquals",
Type.getMethodDescriptor(
Type.getType( boolean.class ),
Type.getType( Object.class ),
Type.getType( Object.class )
),
false
);
branchCode = Opcodes.IFNE;
}
}
Label skip = new Label();
methodVisitor.visitJumpInsn( branchCode, skip );
Expand All @@ -161,7 +216,7 @@ else if ( persistentField.getType().represents( double.class ) ) {
if ( implementationContext.getClassFileVersion().isAtLeast( ClassFileVersion.JAVA_V6 ) ) {
methodVisitor.visitFrame( Opcodes.F_SAME, 0, null, 0, null );
}
return new Size( 1 + 2 * persistentField.getType().asErasure().getStackSize().getSize(), instrumentedMethod.getStackSize() );
return new Size( 3 + 2 * persistentField.getType().asErasure().getStackSize().getSize(), instrumentedMethod.getStackSize() );
}

@Override
Expand Down

0 comments on commit 12d1e30

Please sign in to comment.