org.hibernate.property.access.spi.GetterFieldImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hibernate-core Show documentation
Show all versions of hibernate-core Show documentation
Hibernate's core ORM functionality
/*
* 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 .
*/
package org.hibernate.property.access.spi;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.util.Locale;
import java.util.Map;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.property.access.internal.AbstractFieldSerialForm;
/**
* Field-based implementation of Getter
*
* @author Steve Ebersole
*/
public class GetterFieldImpl implements Getter {
private final Class containerClass;
private final String propertyName;
private final Field field;
private final Method getterMethod;
public GetterFieldImpl(Class containerClass, String propertyName, Field field) {
this.containerClass = containerClass;
this.propertyName = propertyName;
this.field = field;
this.getterMethod = ReflectHelper.findGetterMethodForFieldAccess( field, propertyName );
}
@Override
public Object get(Object owner) {
try {
// This is needed because until JDK 9 the Reflection API
// does not use the same caching as used for auto-boxing.
// See https://bugs.openjdk.java.net/browse/JDK-5043030 for details.
// The code below can be removed when we move to JDK 9.
// double and float are intentionally not handled here because
// the JLS § 5.1.7 does not define caching for boxed values of
// this types.
Class type = field.getType();
if ( type.isPrimitive() ) {
if ( type == Boolean.TYPE ) {
return Boolean.valueOf( field.getBoolean( owner ) );
}
else if ( type == Byte.TYPE ) {
return Byte.valueOf( field.getByte( owner ) );
}
else if ( type == Character.TYPE ) {
return Character.valueOf( field.getChar( owner ) );
}
else if ( type == Integer.TYPE ) {
return Integer.valueOf( field.getInt( owner ) );
}
else if ( type == Long.TYPE ) {
return Long.valueOf( field.getLong( owner ) );
}
else if ( type == Short.TYPE ) {
return Short.valueOf( field.getShort( owner ) );
}
}
return field.get( owner );
}
catch (Exception e) {
throw new PropertyAccessException(
String.format(
Locale.ROOT,
"Error accessing field [%s] by reflection for persistent property [%s#%s] : %s",
field.toGenericString(),
containerClass.getName(),
propertyName,
owner
),
e
);
}
}
@Override
public Object getForInsert(Object owner, Map mergeMap, SharedSessionContractImplementor session) {
return get( owner );
}
@Override
public Class getReturnType() {
return field.getType();
}
@Override
public Member getMember() {
return field;
}
@Override
public String getMethodName() {
return getterMethod != null ? getterMethod.getName() : null;
}
@Override
public Method getMethod() {
return getterMethod;
}
private Object writeReplace() throws ObjectStreamException {
return new SerialForm( containerClass, propertyName, field );
}
private static class SerialForm extends AbstractFieldSerialForm implements Serializable {
private final Class containerClass;
private final String propertyName;
private SerialForm(Class containerClass, String propertyName, Field field) {
super( field );
this.containerClass = containerClass;
this.propertyName = propertyName;
}
private Object readResolve() {
return new GetterFieldImpl( containerClass, propertyName, resolveField() );
}
}
}