HHH-10747 - Instead of the method, use the field directly in the EnhancedSetter
This commit is contained in:
parent
66f11130ca
commit
3080e819d1
|
@ -6,13 +6,11 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.property.access.internal;
|
package org.hibernate.property.access.internal;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import org.hibernate.bytecode.enhance.spi.EnhancerConstants;
|
|
||||||
import org.hibernate.property.access.spi.EnhancedSetterImpl;
|
import org.hibernate.property.access.spi.EnhancedSetterImpl;
|
||||||
import org.hibernate.property.access.spi.PropertyAccessStrategy;
|
import org.hibernate.property.access.spi.PropertyAccessStrategy;
|
||||||
import org.hibernate.property.access.spi.Setter;
|
import org.hibernate.property.access.spi.Setter;
|
||||||
import org.hibernate.property.access.spi.SetterFieldImpl;
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A PropertyAccess for byte code enhanced entities. Enhanced setter methods ( if available ) are used for
|
* A PropertyAccess for byte code enhanced entities. Enhanced setter methods ( if available ) are used for
|
||||||
|
@ -32,20 +30,6 @@ public class PropertyAccessEnhancedImpl extends PropertyAccessMixedImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Setter fieldSetter(Class<?> containerJavaType, String propertyName, Field field) {
|
protected Setter fieldSetter(Class<?> containerJavaType, String propertyName, Field field) {
|
||||||
return resolveEnhancedSetterForField( containerJavaType, propertyName, field );
|
return new EnhancedSetterImpl( containerJavaType, propertyName, field );
|
||||||
}
|
|
||||||
|
|
||||||
private static Setter resolveEnhancedSetterForField(Class<?> containerClass, String propertyName, Field field) {
|
|
||||||
try {
|
|
||||||
String enhancedSetterName = EnhancerConstants.PERSISTENT_FIELD_WRITER_PREFIX + propertyName;
|
|
||||||
Method enhancedSetter = containerClass.getDeclaredMethod( enhancedSetterName, field.getType() );
|
|
||||||
enhancedSetter.setAccessible( true );
|
|
||||||
return new EnhancedSetterImpl( containerClass, propertyName, enhancedSetter );
|
|
||||||
}
|
|
||||||
catch (NoSuchMethodException e) {
|
|
||||||
// enhancedSetter = null --- field not enhanced: fallback to reflection using the field
|
|
||||||
return new SetterFieldImpl( containerClass, propertyName, field );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -6,171 +6,48 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.property.access.spi;
|
package org.hibernate.property.access.spi;
|
||||||
|
|
||||||
import java.io.ObjectStreamException;
|
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
|
||||||
import java.io.Serializable;
|
import org.hibernate.engine.spi.CompositeOwner;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import org.hibernate.engine.spi.CompositeTracker;
|
||||||
import java.lang.reflect.Method;
|
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
|
||||||
|
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
|
||||||
import org.hibernate.PropertyAccessException;
|
|
||||||
import org.hibernate.PropertySetterAccessException;
|
|
||||||
import org.hibernate.engine.spi.SelfDirtinessTracker;
|
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
|
||||||
|
|
||||||
import static org.hibernate.internal.CoreLogging.messageLogger;
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A specialized Setter implementation for handling setting values into
|
* A specialized Setter implementation for handling setting values into
|
||||||
* a into a bytecode-enhanced Class. The reason we need specialized handling
|
* a into a bytecode-enhanced Class. The reason we need specialized handling
|
||||||
* is to render the fact that the
|
* is to render the fact that we need to account for certain enhancement features
|
||||||
|
* during the setting process.
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
* @author Luis Barreiro
|
* @author Luis Barreiro
|
||||||
*/
|
*/
|
||||||
public class EnhancedSetterImpl implements Setter {
|
public class EnhancedSetterImpl extends SetterFieldImpl {
|
||||||
private static final CoreMessageLogger LOG = messageLogger( EnhancedSetterImpl.class );
|
|
||||||
|
|
||||||
private final Class containerClass;
|
|
||||||
private final String propertyName;
|
private final String propertyName;
|
||||||
private final Method setterMethod;
|
|
||||||
|
|
||||||
private final boolean isPrimitive;
|
public EnhancedSetterImpl(Class containerClass, String propertyName, Field field) {
|
||||||
|
super( containerClass, propertyName, field );
|
||||||
public EnhancedSetterImpl(Class containerClass, String propertyName, Method setterMethod) {
|
|
||||||
this.containerClass = containerClass;
|
|
||||||
this.propertyName = propertyName;
|
this.propertyName = propertyName;
|
||||||
this.setterMethod = setterMethod;
|
|
||||||
this.isPrimitive = setterMethod.getParameterTypes()[0].isPrimitive();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void set(Object target, Object value, SessionFactoryImplementor factory) {
|
public void set(Object target, Object value, SessionFactoryImplementor factory) {
|
||||||
try {
|
|
||||||
|
|
||||||
// for enhanced attribute, don't flag as dirty
|
super.set( target, value, factory );
|
||||||
if ( target instanceof SelfDirtinessTracker ) {
|
|
||||||
( (SelfDirtinessTracker) target ).$$_hibernate_suspendDirtyTracking( true );
|
// This sets the component relation for dirty tracking purposes
|
||||||
try {
|
if ( target instanceof CompositeOwner && value instanceof CompositeTracker ) {
|
||||||
setterMethod.invoke( target, value );
|
( (CompositeTracker) value ).$$_hibernate_setOwner( propertyName, (CompositeOwner) target );
|
||||||
}
|
|
||||||
finally {
|
|
||||||
( (SelfDirtinessTracker) target ).$$_hibernate_suspendDirtyTracking( false );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
setterMethod.invoke( target, value );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
// This marks the attribute as initialized, so it doesn't get lazy loaded afterwards
|
||||||
catch (NullPointerException npe) {
|
if ( target instanceof PersistentAttributeInterceptable ) {
|
||||||
if ( value == null && isPrimitive ) {
|
PersistentAttributeInterceptor interceptor = ( (PersistentAttributeInterceptable) target ).$$_hibernate_getInterceptor();
|
||||||
throw new PropertyAccessException(
|
if ( interceptor != null && interceptor instanceof LazyAttributeLoadingInterceptor ) {
|
||||||
npe,
|
interceptor.attributeInitialized( propertyName );
|
||||||
"Null value was assigned to a property of primitive type",
|
|
||||||
true,
|
|
||||||
containerClass,
|
|
||||||
propertyName
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new PropertyAccessException(
|
|
||||||
npe,
|
|
||||||
"NullPointerException occurred while calling",
|
|
||||||
true,
|
|
||||||
containerClass,
|
|
||||||
propertyName
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (InvocationTargetException ite) {
|
|
||||||
throw new PropertyAccessException(
|
|
||||||
ite,
|
|
||||||
"Exception occurred inside",
|
|
||||||
true,
|
|
||||||
containerClass,
|
|
||||||
propertyName
|
|
||||||
);
|
|
||||||
}
|
|
||||||
catch (IllegalAccessException iae) {
|
|
||||||
throw new PropertyAccessException(
|
|
||||||
iae,
|
|
||||||
"IllegalAccessException occurred while calling",
|
|
||||||
true,
|
|
||||||
containerClass,
|
|
||||||
propertyName
|
|
||||||
);
|
|
||||||
//cannot occur
|
|
||||||
}
|
|
||||||
catch (IllegalArgumentException iae) {
|
|
||||||
if ( value == null && isPrimitive ) {
|
|
||||||
throw new PropertyAccessException(
|
|
||||||
iae,
|
|
||||||
"Null value was assigned to a property of primitive type",
|
|
||||||
true,
|
|
||||||
containerClass,
|
|
||||||
propertyName
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
final Class expectedType = setterMethod.getParameterTypes()[0];
|
|
||||||
LOG.illegalPropertySetterArgument( containerClass.getName(), propertyName );
|
|
||||||
LOG.expectedType( expectedType.getName(), value == null ? null : value.getClass().getName() );
|
|
||||||
throw new PropertySetterAccessException(
|
|
||||||
iae,
|
|
||||||
containerClass,
|
|
||||||
propertyName,
|
|
||||||
expectedType,
|
|
||||||
target,
|
|
||||||
value
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getMethodName() {
|
|
||||||
return setterMethod.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Method getMethod() {
|
|
||||||
return setterMethod;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Object writeReplace() throws ObjectStreamException {
|
|
||||||
return new SerialForm( containerClass, propertyName, setterMethod );
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class SerialForm implements Serializable {
|
|
||||||
private final Class containerClass;
|
|
||||||
private final String propertyName;
|
|
||||||
|
|
||||||
private final Class declaringClass;
|
|
||||||
private final String methodName;
|
|
||||||
private final Class argumentType;
|
|
||||||
|
|
||||||
private SerialForm(Class containerClass, String propertyName, Method method) {
|
|
||||||
this.containerClass = containerClass;
|
|
||||||
this.propertyName = propertyName;
|
|
||||||
this.declaringClass = method.getDeclaringClass();
|
|
||||||
this.methodName = method.getName();
|
|
||||||
this.argumentType = method.getParameterTypes()[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
private Object readResolve() {
|
|
||||||
return new EnhancedSetterImpl( containerClass, propertyName, resolveMethod() );
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private Method resolveMethod() {
|
|
||||||
try {
|
|
||||||
return declaringClass.getDeclaredMethod( methodName, argumentType );
|
|
||||||
}
|
|
||||||
catch (NoSuchMethodException e) {
|
|
||||||
throw new PropertyAccessSerializationException(
|
|
||||||
"Unable to resolve setter method on deserialization : " + declaringClass.getName() + "#"
|
|
||||||
+ methodName + "(" + argumentType.getName() + ")"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue