HHH-15634 Lazy basic property does not get updated on change: inline dirty checking, lazy basic properties are not upated when set to null
This commit is contained in:
parent
6d99eb1068
commit
90b1cfe2c3
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@ import jakarta.persistence.Id;
|
|||
|
||||
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;
|
||||
|
@ -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(
|
||||
|
@ -57,8 +64,12 @@ final class InlineDirtyCheckingHandler implements Implementation, ByteCodeAppend
|
|||
&& !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() )
|
||||
|
@ -99,6 +110,11 @@ final class InlineDirtyCheckingHandler implements Implementation, ByteCodeAppend
|
|||
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 ) ) {
|
||||
|
@ -119,30 +135,69 @@ final class InlineDirtyCheckingHandler implements Implementation, ByteCodeAppend
|
|||
);
|
||||
}
|
||||
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 );
|
||||
|
@ -161,7 +216,7 @@ final class InlineDirtyCheckingHandler implements Implementation, ByteCodeAppend
|
|||
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
|
||||
|
|
Loading…
Reference in New Issue