Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 26 additions & 9 deletions hibernate-core/src/main/java/org/hibernate/Hibernate.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 <E> boolean isPropertyInitialized(E entity, Attribute<? super E, ?> attribute) {
public static <E> boolean isPropertyInitialized(E entity, Attribute<? super E, ?> 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}.
* <p>
* 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;
Expand All @@ -348,12 +352,25 @@ && getAttributeInterceptor( entity )
}

/**
* Initializes the property with the given name of the given entity instance.
* <p>
* 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 <E> void initializeProperty(E entity, Attribute<? super E, ?> 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 );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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() ) {
Expand All @@ -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).
Expand Down Expand Up @@ -328,7 +331,7 @@ public ClassMetadataCache(Class<?> clazz) {
}

private static List<Class<?>> findClassHierarchy(Class<?> clazz) {
List<Class<?>> classes = new ArrayList<>();
final List<Class<?>> classes = new ArrayList<>();
Class<?> current = clazz;
do {
classes.add( current );
Expand Down Expand Up @@ -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 );
}
Expand Down