diff --git a/hibernate-core/src/main/java/org/hibernate/Hibernate.java b/hibernate-core/src/main/java/org/hibernate/Hibernate.java index dd87ed78a837..7eca767ac5ca 100644 --- a/hibernate-core/src/main/java/org/hibernate/Hibernate.java +++ b/hibernate-core/src/main/java/org/hibernate/Hibernate.java @@ -302,27 +302,31 @@ public static boolean isInstance(Object proxy, Class entityClass) { /** * Determines if the given attribute of the given entity instance is initialized. + * This operation returns {@code true} if the field or property references an + * unfetched collection or proxy. * * @param entity The entity instance or proxy * @param attribute A persistent attribute of the entity * @return true if the named property of the object is not listed as uninitialized; * false otherwise */ - public boolean isPropertyInitialized(E entity, Attribute attribute) { + public static boolean isPropertyInitialized(E entity, Attribute attribute) { return isPropertyInitialized( entity, attribute.getName() ); } /** - * Determines if the property with the given name of the given entity instance is - * initialized. If the named property does not exist or is not persistent, this - * method always returns {@code true}. - *

- * This operation is equivalent to {@link jakarta.persistence.PersistenceUtil#isLoaded(Object, String)}. + * Determines if the field or property with the given name of the given entity + * instance is initialized. If the named property does not exist or is not + * persistent, this method always returns {@code true}. This operation returns + * {@code true} if the field or property references an unfetched collection or + * proxy. * * @param proxy The entity instance or proxy * @param attributeName the name of a persistent attribute of the object * @return true if the named property of the object is not listed as uninitialized; * false otherwise + * + * @see jakarta.persistence.PersistenceUtil#isLoaded(Object, String) */ public static boolean isPropertyInitialized(Object proxy, String attributeName) { final Object entity; @@ -348,12 +352,25 @@ && getAttributeInterceptor( entity ) } /** - * Initializes the property with the given name of the given entity instance. - *

- * This operation is equivalent to {@link jakarta.persistence.PersistenceUnitUtil#load(Object, String)}. + * Initializes the given attribute of the given entity instance. This operation + * does not fetch a collection or proxy referenced by the field or property. + * + * @param entity The entity instance or proxy + * @param attribute A persistent attribute of the entity + */ + public static void initializeProperty(E entity, Attribute attribute) { + initializeProperty( entity, attribute.getName() ); + } + + /** + * Initializes the field or property with the given name of the given entity + * instance. This operation does not fetch a collection or proxy referenced + * by the field or property. * * @param proxy The entity instance or proxy * @param attributeName the name of a persistent attribute of the object + * + * @see jakarta.persistence.PersistenceUnitUtil#load(Object, String) */ public static void initializeProperty(Object proxy, String attributeName) { final LazyInitializer lazyInitializer = extractLazyInitializer( proxy ); diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/internal/util/PersistenceUtilHelper.java b/hibernate-core/src/main/java/org/hibernate/jpa/internal/util/PersistenceUtilHelper.java index 2a53d1d94708..1bee91e34ed0 100644 --- a/hibernate-core/src/main/java/org/hibernate/jpa/internal/util/PersistenceUtilHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/jpa/internal/util/PersistenceUtilHelper.java @@ -88,8 +88,8 @@ public static LoadState getLoadState(Object reference) { else if ( isPersistentAttributeInterceptable( reference ) ) { return isInitialized( asPersistentAttributeInterceptable( reference ) ) ? LOADED : NOT_LOADED; } - else if ( reference instanceof LazyInitializable) { - return ( (LazyInitializable) reference ).wasInitialized() ? LOADED : NOT_LOADED; + else if ( reference instanceof LazyInitializable lazyInitializable) { + return lazyInitializable.wasInitialized() ? LOADED : NOT_LOADED; } else { return UNKNOWN; @@ -116,7 +116,7 @@ private static BytecodeLazyAttributeInterceptor extractInterceptor(PersistentAtt * @return The LoadState */ public static LoadState isLoadedWithoutReference(Object entity, String attributeName, MetadataCache cache) { - boolean sureFromUs = false; + final boolean sureFromUs; final LazyInitializer lazyInitializer = extractLazyInitializer( entity ); if ( lazyInitializer != null ) { if ( lazyInitializer.isUninitialized() ) { @@ -129,54 +129,57 @@ public static LoadState isLoadedWithoutReference(Object entity, String attribute } sureFromUs = true; } + else { + sureFromUs = false; + } // we are instrumenting, but we can't assume we are the only ones if ( isPersistentAttributeInterceptable( entity ) ) { - final BytecodeLazyAttributeInterceptor interceptor = extractInterceptor( asPersistentAttributeInterceptable( entity ) ); + final BytecodeLazyAttributeInterceptor interceptor = + extractInterceptor( asPersistentAttributeInterceptable( entity ) ); final boolean isInitialized = interceptor == null || interceptor.isAttributeLoaded( attributeName ); - LoadState state; - if (isInitialized && interceptor != null) { - // attributeName is loaded according to bytecode enhancement, but is it loaded as far as association? - // it's ours, we can read - try { - state = getLoadState( getAttributeValue( entity, attributeName, cache ) ); - // it's ours so we know it's loaded - if ( state == UNKNOWN ) { - state = LOADED; - } - } - catch (AttributeExtractionException ignore) { - state = UNKNOWN; - } - } - else if ( interceptor != null ) { - 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 { - state = getLoadState( getAttributeValue( entity, attributeName, cache ) ); - // it's ours so we know it's loaded - if ( state == UNKNOWN ) { - state = LOADED; - } - } - catch (AttributeExtractionException ignore) { - state = UNKNOWN; - } - } - else { - state = UNKNOWN; - } + return getLoadState( entity, attributeName, cache, isInitialized, interceptor, sureFromUs ); + } + else { + return UNKNOWN; + } + } - return state; + private static LoadState getLoadState( + Object entity, String attributeName, + MetadataCache cache, + boolean isInitialized, + BytecodeLazyAttributeInterceptor interceptor, + boolean sureFromUs) { + if ( isInitialized && interceptor != null) { + // attributeName is loaded according to bytecode enhancement, but is it loaded as far as association? + // it's ours, we can read + return getLoadState( entity, attributeName, cache ); + } + else if ( interceptor != null ) { + return 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 + return getLoadState( entity, attributeName, cache ); } else { return UNKNOWN; } } + private static LoadState getLoadState(Object entity, String attributeName, MetadataCache cache) { + try { + final LoadState state = getLoadState( getAttributeValue( entity, attributeName, cache ) ); + // it's ours so we know it's loaded + return state == UNKNOWN ? LOADED : state; + } + catch (AttributeExtractionException ignore) { + return UNKNOWN; + } + } + /** * Is the given attribute (by name) loaded? This form must take care to not access the attribute (trigger * initialization). @@ -328,7 +331,7 @@ public ClassMetadataCache(Class clazz) { } private static List> findClassHierarchy(Class clazz) { - List> classes = new ArrayList<>(); + final List> classes = new ArrayList<>(); Class current = clazz; do { classes.add( current ); @@ -374,9 +377,9 @@ private AttributeAccess buildAttributeAccess(final String attributeName) { */ private static Method getMethod(Class clazz, String attributeName) { try { - char[] string = attributeName.toCharArray(); + final char[] string = attributeName.toCharArray(); string[0] = Character.toUpperCase( string[0] ); - String casedAttributeName = new String( string ); + final String casedAttributeName = new String( string ); try { return clazz.getDeclaredMethod( "get" + casedAttributeName ); }