raft of minor code cleanups

This commit is contained in:
Gavin 2023-05-20 12:10:36 +02:00 committed by Gavin King
parent 4247f7b155
commit fb28443081
6 changed files with 90 additions and 104 deletions

View File

@ -37,15 +37,16 @@ import org.hibernate.collection.spi.LazyInitializable;
import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable;
import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable;
import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer;
/**
* Various utility functions for working with proxies and lazy collection references.
* <p>
* Operations like {@link #isInitialized(Object)} and {@link #initialize(Object)} are
* of general purpose. But {@link #createDetachedProxy(SessionFactory, Class, Object)}
* and {@link CollectionInterface#createDetachedProxy(SessionFactory, Class, Object)}
* are intended for use by generic code that must materialize an "amputated" graph of
* Hibernate entities. (For example, a library which deserializes entities from JSON.)
* and {@link CollectionInterface#createDetachedInstance()} are intended for use by
* generic code that must materialize an "amputated" graph of Hibernate entities.
* (For example, a library which deserializes entities from JSON.)
* <p>
* Lazy fetching of a {@linkplain jakarta.persistence.OneToOne one to one} or
* {@linkplain jakarta.persistence.ManyToOne many to one} association requires special
@ -126,7 +127,7 @@ public final class Hibernate {
return;
}
final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( proxy );
final LazyInitializer lazyInitializer = extractLazyInitializer( proxy );
if ( lazyInitializer != null ) {
lazyInitializer.initialize();
}
@ -134,7 +135,8 @@ public final class Hibernate {
( (LazyInitializable) proxy ).forceInitialization();
}
else if ( isPersistentAttributeInterceptable( proxy ) ) {
final PersistentAttributeInterceptor interceptor = asPersistentAttributeInterceptable( proxy ).$$_hibernate_getInterceptor();
final PersistentAttributeInterceptor interceptor =
asPersistentAttributeInterceptable( proxy ).$$_hibernate_getInterceptor();
if ( interceptor instanceof EnhancementAsProxyLazinessInterceptor ) {
( (EnhancementAsProxyLazinessInterceptor) interceptor ).forceInitialize( proxy, null );
}
@ -150,12 +152,13 @@ public final class Hibernate {
* @return true if the argument is already initialized, or is not a proxy or collection
*/
public static boolean isInitialized(Object proxy) {
final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( proxy );
final LazyInitializer lazyInitializer = extractLazyInitializer( proxy );
if ( lazyInitializer != null ) {
return !lazyInitializer.isUninitialized();
}
else if ( isPersistentAttributeInterceptable( proxy ) ) {
final PersistentAttributeInterceptor interceptor = asPersistentAttributeInterceptable( proxy ).$$_hibernate_getInterceptor();
final PersistentAttributeInterceptor interceptor =
asPersistentAttributeInterceptable( proxy ).$$_hibernate_getInterceptor();
if (interceptor instanceof EnhancementAsProxyLazinessInterceptor) {
return ( (EnhancementAsProxyLazinessInterceptor) interceptor ).isInitialized();
}
@ -294,7 +297,7 @@ public final class Hibernate {
@SuppressWarnings("unchecked")
public static <T> Class<? extends T> getClass(T proxy) {
Class<?> result;
final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( proxy );
final LazyInitializer lazyInitializer = extractLazyInitializer( proxy );
if ( lazyInitializer != null ) {
result = lazyInitializer
.getImplementation()
@ -334,7 +337,7 @@ public final class Hibernate {
*/
public static boolean isPropertyInitialized(Object proxy, String propertyName) {
final Object entity;
final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( proxy );
final LazyInitializer lazyInitializer = extractLazyInitializer( proxy );
if ( lazyInitializer != null ) {
if ( lazyInitializer.isUninitialized() ) {
return false;
@ -369,7 +372,7 @@ public final class Hibernate {
* uninitialized proxy that is not associated with an open session.
*/
public static Object unproxy(Object proxy) {
final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( proxy );
final LazyInitializer lazyInitializer = extractLazyInitializer( proxy );
if ( lazyInitializer != null ) {
return lazyInitializer.getImplementation();
}
@ -397,7 +400,7 @@ public final class Hibernate {
/**
* Obtain a detached, uninitialized reference (a proxy) for a persistent entity with
* the given identifier.
*
* <p>
* The returned proxy is not associated with any session, and cannot be initialized
* by calling {@link #initialize(Object)}. It can be used to represent a reference to
* the entity when working with a detached object graph.
@ -441,7 +444,7 @@ public final class Hibernate {
/**
* Obtain a detached, uninitialized persistent collection of the type represented
* by this object.
*
* <p>
* The returned wrapper object is not associated with any session, and cannot be
* initialized by calling {@link #initialize(Object)}. It can be used to represent
* an uninitialized collection when working with a detached object graph.

View File

@ -189,8 +189,8 @@ public class HibernatePersistenceProvider implements PersistenceProvider {
return PersistenceUtilHelper.isLoadedWithReference( proxy, property, cache );
}
@Override
public LoadState isLoaded(Object o) {
return PersistenceUtilHelper.isLoaded(o);
public LoadState isLoaded(Object object) {
return PersistenceUtilHelper.getLoadState( object );
}
};

View File

@ -8,7 +8,6 @@ package org.hibernate.jpa.internal;
import java.io.Serializable;
import jakarta.persistence.PersistenceUnitUtil;
import jakarta.persistence.spi.LoadState;
import org.hibernate.Hibernate;
import org.hibernate.MappingException;
@ -16,13 +15,17 @@ import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.jpa.internal.util.PersistenceUtilHelper;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import org.jboss.logging.Logger;
import static jakarta.persistence.spi.LoadState.NOT_LOADED;
import static org.hibernate.engine.internal.ManagedTypeHelper.asManagedEntity;
import static org.hibernate.engine.internal.ManagedTypeHelper.isManagedEntity;
import static org.hibernate.jpa.internal.util.PersistenceUtilHelper.getLoadState;
import static org.hibernate.jpa.internal.util.PersistenceUtilHelper.isLoadedWithReference;
import static org.hibernate.jpa.internal.util.PersistenceUtilHelper.isLoadedWithoutReference;
import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer;
/**
* @author Steve Ebersole
@ -41,19 +44,13 @@ public class PersistenceUnitUtilImpl implements PersistenceUnitUtil, Serializabl
public boolean isLoaded(Object entity, String attributeName) {
// added log message to help with HHH-7454, if state == LoadState,NOT_LOADED, returning true or false is not accurate.
log.debug( "PersistenceUnitUtil#isLoaded is not always accurate; consider using EntityManager#contains instead" );
LoadState state = PersistenceUtilHelper.isLoadedWithoutReference( entity, attributeName, cache );
if ( state == LoadState.LOADED ) {
return true;
}
else if ( state == LoadState.NOT_LOADED ) {
return false;
}
else {
return PersistenceUtilHelper.isLoadedWithReference(
entity,
attributeName,
cache
) != LoadState.NOT_LOADED;
switch ( isLoadedWithoutReference( entity, attributeName, cache ) ) {
case LOADED:
return true;
case NOT_LOADED:
return false;
default:
return isLoadedWithReference( entity, attributeName, cache ) != NOT_LOADED;
}
}
@ -61,7 +58,7 @@ public class PersistenceUnitUtilImpl implements PersistenceUnitUtil, Serializabl
public boolean isLoaded(Object entity) {
// added log message to help with HHH-7454, if state == LoadState,NOT_LOADED, returning true or false is not accurate.
log.debug( "PersistenceUnitUtil#isLoaded is not always accurate; consider using EntityManager#contains instead" );
return PersistenceUtilHelper.isLoaded( entity ) != LoadState.NOT_LOADED;
return getLoadState( entity ) != NOT_LOADED;
}
@Override
@ -70,12 +67,12 @@ public class PersistenceUnitUtilImpl implements PersistenceUnitUtil, Serializabl
throw new IllegalArgumentException( "Passed entity cannot be null" );
}
final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( entity );
final LazyInitializer lazyInitializer = extractLazyInitializer( entity );
if ( lazyInitializer != null ) {
return lazyInitializer.getInternalIdentifier();
}
else if ( isManagedEntity( entity ) ) {
EntityEntry entityEntry = asManagedEntity( entity ).$$_hibernate_getEntityEntry();
final EntityEntry entityEntry = asManagedEntity( entity ).$$_hibernate_getEntityEntry();
if ( entityEntry != null ) {
return entityEntry.getId();
}
@ -96,7 +93,7 @@ public class PersistenceUnitUtilImpl implements PersistenceUnitUtil, Serializabl
}
private Object getIdentifierFromPersister(Object entity) {
Class<?> entityClass = Hibernate.getClass( entity );
final Class<?> entityClass = Hibernate.getClass( entity );
final EntityPersister persister;
try {
persister = sessionFactory.getRuntimeMetamodels()

View File

@ -11,7 +11,6 @@ import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.HashMap;
@ -23,6 +22,7 @@ import jakarta.persistence.spi.LoadState;
import org.hibernate.HibernateException;
import org.hibernate.bytecode.enhance.spi.interceptor.BytecodeLazyAttributeInterceptor;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
import org.hibernate.collection.spi.LazyInitializable;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.internal.util.ReflectHelper;
@ -30,8 +30,13 @@ import org.hibernate.internal.util.securitymanager.SystemSecurityManager;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import static jakarta.persistence.spi.LoadState.LOADED;
import static jakarta.persistence.spi.LoadState.NOT_LOADED;
import static jakarta.persistence.spi.LoadState.UNKNOWN;
import static java.security.AccessController.doPrivileged;
import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable;
import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable;
import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer;
/**
* Central delegate for handling calls from:<ul>
@ -80,28 +85,25 @@ public final class PersistenceUtilHelper {
*
* @return The appropriate LoadState (see above)
*/
public static LoadState isLoaded(Object reference) {
final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( reference );
public static LoadState getLoadState(Object reference) {
final LazyInitializer lazyInitializer = extractLazyInitializer( reference );
if ( lazyInitializer != null ) {
final boolean isInitialized = !lazyInitializer.isUninitialized();
return isInitialized ? LoadState.LOADED : LoadState.NOT_LOADED;
return !lazyInitializer.isUninitialized() ? LOADED : NOT_LOADED;
}
else if ( isPersistentAttributeInterceptable( reference ) ) {
boolean isInitialized = isInitialized( asPersistentAttributeInterceptable( reference ) );
return isInitialized ? LoadState.LOADED : LoadState.NOT_LOADED;
return isInitialized( asPersistentAttributeInterceptable( reference ) ) ? LOADED : NOT_LOADED;
}
else if ( reference instanceof PersistentCollection ) {
final boolean isInitialized = ( (PersistentCollection<?>) reference ).wasInitialized();
return isInitialized ? LoadState.LOADED : LoadState.NOT_LOADED;
else if ( reference instanceof LazyInitializable) {
return ( (LazyInitializable) reference ).wasInitialized() ? LOADED : NOT_LOADED;
}
else {
return LoadState.UNKNOWN;
return UNKNOWN;
}
}
private static boolean isInitialized(PersistentAttributeInterceptable interceptable) {
final BytecodeLazyAttributeInterceptor interceptor = extractInterceptor( interceptable );
return interceptable == null || interceptor == null || !interceptor.hasAnyUninitializedAttributes();
return interceptor == null || !interceptor.hasAnyUninitializedAttributes();
}
private static BytecodeLazyAttributeInterceptor extractInterceptor(PersistentAttributeInterceptable interceptable) {
@ -120,11 +122,11 @@ public final class PersistenceUtilHelper {
*/
public static LoadState isLoadedWithoutReference(Object entity, String attributeName, MetadataCache cache) {
boolean sureFromUs = false;
final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( entity );
final LazyInitializer lazyInitializer = extractLazyInitializer( entity );
if ( lazyInitializer != null ) {
if ( lazyInitializer.isUninitialized() ) {
// we have an uninitialized proxy, the attribute cannot be loaded
return LoadState.NOT_LOADED;
return NOT_LOADED;
}
else {
// swap the proxy with target (for proper class name resolution)
@ -133,7 +135,7 @@ public final class PersistenceUtilHelper {
sureFromUs = true;
}
// we are instrumenting but we can't assume we are the only ones
// we are instrumenting, but we can't assume we are the only ones
if ( isPersistentAttributeInterceptable( entity ) ) {
final BytecodeLazyAttributeInterceptor interceptor = extractInterceptor( asPersistentAttributeInterceptable( entity ) );
final boolean isInitialized = interceptor == null || interceptor.isAttributeLoaded( attributeName );
@ -142,55 +144,44 @@ public final class PersistenceUtilHelper {
// attributeName is loaded according to bytecode enhancement, but is it loaded as far as association?
// it's ours, we can read
try {
final Class entityClass = entity.getClass();
final Object attributeValue = cache.getClassMetadata( entityClass )
.getAttributeAccess( attributeName )
.extractValue( entity );
state = isLoaded( attributeValue );
state = getLoadState( getAttributeValue( entity, attributeName, cache ) );
// it's ours so we know it's loaded
if ( state == LoadState.UNKNOWN ) {
state = LoadState.LOADED;
if ( state == UNKNOWN ) {
state = LOADED;
}
}
catch (AttributeExtractionException ignore) {
state = LoadState.UNKNOWN;
state = UNKNOWN;
}
}
else if ( interceptor != null ) {
state = LoadState.NOT_LOADED;
state = NOT_LOADED;
}
else if ( sureFromUs ) {
// property is loaded according to bytecode enhancement, but is it loaded as far as association?
// it's ours, we can read
try {
final Class entityClass = entity.getClass();
final Object attributeValue = cache.getClassMetadata( entityClass )
.getAttributeAccess( attributeName )
.extractValue( entity );
state = isLoaded( attributeValue );
state = getLoadState( getAttributeValue( entity, attributeName, cache ) );
// it's ours so we know it's loaded
if ( state == LoadState.UNKNOWN ) {
state = LoadState.LOADED;
if ( state == UNKNOWN ) {
state = LOADED;
}
}
catch (AttributeExtractionException ignore) {
state = LoadState.UNKNOWN;
state = UNKNOWN;
}
}
else {
state = LoadState.UNKNOWN;
state = UNKNOWN;
}
return state;
}
else {
return LoadState.UNKNOWN;
return UNKNOWN;
}
}
/**
* Is the given attribute (by name) loaded? This form must take care to not access the attribute (trigger
* initialization).
@ -202,11 +193,11 @@ public final class PersistenceUtilHelper {
* @return The LoadState
*/
public static LoadState isLoadedWithReference(Object entity, String attributeName, MetadataCache cache) {
final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( entity );
final LazyInitializer lazyInitializer = extractLazyInitializer( entity );
if ( lazyInitializer != null ) {
if ( lazyInitializer.isUninitialized() ) {
// we have an uninitialized proxy, the attribute cannot be loaded
return LoadState.NOT_LOADED;
return NOT_LOADED;
}
else {
// swap the proxy with target (for proper class name resolution)
@ -215,17 +206,18 @@ public final class PersistenceUtilHelper {
}
try {
final Class entityClass = entity.getClass();
final Object attributeValue = cache.getClassMetadata( entityClass )
.getAttributeAccess( attributeName )
.extractValue( entity );
return isLoaded( attributeValue );
return getLoadState( getAttributeValue( entity, attributeName, cache ) );
}
catch (AttributeExtractionException ignore) {
return LoadState.UNKNOWN;
return UNKNOWN;
}
}
private static Object getAttributeValue(Object entity, String attributeName, MetadataCache cache) {
return cache.getClassMetadata( entity.getClass() )
.getAttributeAccess( attributeName )
.extractValue( entity );
}
public static class AttributeExtractionException extends HibernateException {
public AttributeExtractionException(String message) {
@ -316,10 +308,10 @@ public final class PersistenceUtilHelper {
}
private static class NoSuchAttributeAccess implements AttributeAccess {
private final Class clazz;
private final Class<?> clazz;
private final String attributeName;
public NoSuchAttributeAccess(Class clazz, String attributeName) {
public NoSuchAttributeAccess(Class<?> clazz, String attributeName) {
this.clazz = clazz;
this.attributeName = attributeName;
}
@ -331,9 +323,9 @@ public final class PersistenceUtilHelper {
}
public static class ClassMetadataCache {
private final Class specifiedClass;
private List<Class<?>> classHierarchy;
private Map<String, AttributeAccess> attributeAccessMap = new HashMap<>();
private final Class<?> specifiedClass;
private final List<Class<?>> classHierarchy;
private final Map<String, AttributeAccess> attributeAccessMap = new HashMap<>();
public ClassMetadataCache(Class<?> clazz) {
this.specifiedClass = clazz;
@ -361,28 +353,22 @@ public final class PersistenceUtilHelper {
}
private AttributeAccess buildAttributeAccess(final String attributeName) {
final PrivilegedAction<AttributeAccess> action = new PrivilegedAction<AttributeAccess>() {
@Override
public AttributeAccess run() {
for ( Class clazz : classHierarchy ) {
try {
final Field field = clazz.getDeclaredField( attributeName );
if ( field != null ) {
return new FieldAttributeAccess( field );
}
}
catch ( NoSuchFieldException e ) {
final Method method = getMethod( clazz, attributeName );
if ( method != null ) {
return new MethodAttributeAccess( attributeName, method );
}
final PrivilegedAction<AttributeAccess> action = () -> {
for ( Class<?> clazz : classHierarchy ) {
try {
return new FieldAttributeAccess( clazz.getDeclaredField( attributeName ) );
}
catch ( NoSuchFieldException e ) {
final Method method = getMethod( clazz, attributeName );
if ( method != null ) {
return new MethodAttributeAccess( attributeName, method );
}
}
//we could not find any match
return new NoSuchAttributeAccess( specifiedClass, attributeName );
}
//we could not find any match
return new NoSuchAttributeAccess( specifiedClass, attributeName );
};
return SystemSecurityManager.isSecurityManagerEnabled() ? AccessController.doPrivileged( action ) : action.run();
return SystemSecurityManager.isSecurityManagerEnabled() ? doPrivileged( action ) : action.run();
}
}

View File

@ -130,7 +130,7 @@ public class PersistenceUtilHelperTest {
public void testIsLoadedWithNullInterceptor() {
assertEquals(
LoadState.LOADED,
PersistenceUtilHelper.isLoaded(
PersistenceUtilHelper.getLoadState(
new PersistentAttributeInterceptable() {
@Override

View File

@ -28,14 +28,14 @@ public class ProviderUtilTest extends BaseEntityManagerFunctionalTestCase {
public void testIsLoadedOnUnknownClass() {
final Object entity = new Object();
assertTrue( Persistence.getPersistenceUtil().isLoaded( entity ) );
assertEquals( LoadState.UNKNOWN, PersistenceUtilHelper.isLoaded( entity ) );
assertEquals( LoadState.UNKNOWN, PersistenceUtilHelper.getLoadState( entity ) );
}
@Test
public void testIsLoadedOnKnownClass() {
final Author entity = new Author();
assertTrue( Persistence.getPersistenceUtil().isLoaded( entity ) );
assertEquals( LoadState.UNKNOWN, PersistenceUtilHelper.isLoaded( entity ) );
assertEquals( LoadState.UNKNOWN, PersistenceUtilHelper.getLoadState( entity ) );
}
@Test