-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
HHH-14097 Fix redundant SQLs issue for fetch entity graph #3453
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -206,62 +206,91 @@ public static void initializeEntityEntryLoadedState( | |
String entityName = persister.getEntityName(); | ||
String[] propertyNames = persister.getPropertyNames(); | ||
final Type[] types = persister.getPropertyTypes(); | ||
|
||
final GraphImplementor<?> fetchGraphContext = session.getFetchGraphLoadContext(); | ||
|
||
for ( int i = 0; i < hydratedState.length; i++ ) { | ||
final Object value = hydratedState[i]; | ||
if ( debugEnabled ) { | ||
LOG.debugf( | ||
"Processing attribute `%s` : value = %s", | ||
propertyNames[i], | ||
value == LazyPropertyInitializer.UNFETCHED_PROPERTY ? "<un-fetched>" : value == PropertyAccessStrategyBackRefImpl.UNKNOWN ? "<unknown>" : value | ||
); | ||
} | ||
|
||
if ( value == LazyPropertyInitializer.UNFETCHED_PROPERTY ) { | ||
GraphImplementor fetchGraphContext = session.getFetchGraphLoadContext(); | ||
if ( fetchGraphContext != null && !fetchGraphContext.appliesTo( entity.getClass() ) ) { | ||
LOG.warnf( "Entity graph specified is not applicable to the entity [%s]. Ignored.", entity); | ||
fetchGraphContext = null; | ||
session.setFetchGraphLoadContext( null ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just a minor but I think the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it is necessary because without setting it, the downstream will still try to locate some property as per the context grabbed from I am sorry the current fetch entity graph implementation is so difficult to understand (and maintain). Luckily its status is improved much more in v6. |
||
} | ||
|
||
try { | ||
for ( int i = 0; i < hydratedState.length; i++ ) { | ||
final Object value = hydratedState[i]; | ||
if ( debugEnabled ) { | ||
LOG.debugf( "Resolving <un-fetched> attribute : `%s`", propertyNames[i] ); | ||
LOG.debugf( | ||
"Processing attribute `%s` : value = %s", | ||
propertyNames[i], | ||
value == LazyPropertyInitializer.UNFETCHED_PROPERTY ? | ||
"<un-fetched>" : | ||
value == PropertyAccessStrategyBackRefImpl.UNKNOWN ? "<unknown>" : value | ||
); | ||
} | ||
|
||
// IMPLEMENTATION NOTE: This is a lazy property on a bytecode-enhanced entity. | ||
// hydratedState[i] needs to remain LazyPropertyInitializer.UNFETCHED_PROPERTY so that | ||
// setPropertyValues() below (ultimately AbstractEntityTuplizer#setPropertyValues) works properly | ||
// No resolution is necessary, unless the lazy property is a collection. | ||
if ( types[i].isCollectionType() ) { | ||
// IMPLEMENTATION NOTE: this is a lazy collection property on a bytecode-enhanced entity. | ||
// HHH-10989: We need to resolve the collection so that a CollectionReference is added to StatefulPersistentContext. | ||
// As mentioned above, hydratedState[i] needs to remain LazyPropertyInitializer.UNFETCHED_PROPERTY | ||
// so do not assign the resolved, uninitialized PersistentCollection back to hydratedState[i]. | ||
Boolean overridingEager = getOverridingEager( session, entityName, propertyNames[i], types[i], debugEnabled ); | ||
types[i].resolve( value, session, entity, overridingEager ); | ||
} | ||
} | ||
else if ( value != PropertyAccessStrategyBackRefImpl.UNKNOWN ) { | ||
if ( debugEnabled ) { | ||
final boolean isLazyEnhanced = persister.getBytecodeEnhancementMetadata() | ||
.getLazyAttributesMetadata() | ||
.getLazyAttributeNames() | ||
.contains( propertyNames[i] ); | ||
LOG.debugf( "Attribute (`%s`) - enhanced for lazy-loading? - %s", propertyNames[i], isLazyEnhanced ); | ||
if ( value == LazyPropertyInitializer.UNFETCHED_PROPERTY ) { | ||
if ( debugEnabled ) { | ||
LOG.debugf( "Resolving <un-fetched> attribute : `%s`", propertyNames[i] ); | ||
} | ||
|
||
// IMPLEMENTATION NOTE: This is a lazy property on a bytecode-enhanced entity. | ||
// hydratedState[i] needs to remain LazyPropertyInitializer.UNFETCHED_PROPERTY so that | ||
// setPropertyValues() below (ultimately AbstractEntityTuplizer#setPropertyValues) works properly | ||
// No resolution is necessary, unless the lazy property is a collection. | ||
if ( types[i].isCollectionType() ) { | ||
// IMPLEMENTATION NOTE: this is a lazy collection property on a bytecode-enhanced entity. | ||
// HHH-10989: We need to resolve the collection so that a CollectionReference is added to StatefulPersistentContext. | ||
// As mentioned above, hydratedState[i] needs to remain LazyPropertyInitializer.UNFETCHED_PROPERTY | ||
// so do not assign the resolved, uninitialized PersistentCollection back to hydratedState[i]. | ||
Boolean overridingEager = getOverridingEager( | ||
session, | ||
entityName, | ||
propertyNames[i], | ||
types[i], | ||
debugEnabled | ||
); | ||
types[i].resolve( value, session, entity, overridingEager ); | ||
} | ||
} | ||
else if ( value != PropertyAccessStrategyBackRefImpl.UNKNOWN ) { | ||
if ( debugEnabled ) { | ||
final boolean isLazyEnhanced = persister.getBytecodeEnhancementMetadata() | ||
.getLazyAttributesMetadata() | ||
.getLazyAttributeNames() | ||
.contains( propertyNames[i] ); | ||
LOG.debugf( | ||
"Attribute (`%s`) - enhanced for lazy-loading? - %s", | ||
propertyNames[i], | ||
isLazyEnhanced | ||
); | ||
} | ||
|
||
// we know value != LazyPropertyInitializer.UNFETCHED_PROPERTY | ||
Boolean overridingEager = getOverridingEager( session, entityName, propertyNames[i], types[i], debugEnabled ); | ||
hydratedState[i] = types[i].isEntityType() | ||
? entityResolver.resolve( (EntityType) types[i], value, session, entity, overridingEager ) | ||
: types[i].resolve( value, session, entity, overridingEager ); | ||
} | ||
else { | ||
if ( debugEnabled ) { | ||
LOG.debugf( "Skipping <unknown> attribute : `%s`", propertyNames[i] ); | ||
// we know value != LazyPropertyInitializer.UNFETCHED_PROPERTY | ||
Boolean overridingEager = getOverridingEager( | ||
session, | ||
entityName, | ||
propertyNames[i], | ||
types[i], | ||
debugEnabled | ||
); | ||
hydratedState[i] = types[i].isEntityType() | ||
? entityResolver.resolve( (EntityType) types[i], value, session, entity, overridingEager ) | ||
: types[i].resolve( value, session, entity, overridingEager ); | ||
} | ||
else { | ||
if ( debugEnabled ) { | ||
LOG.debugf( "Skipping <unknown> attribute : `%s`", propertyNames[i] ); | ||
} | ||
} | ||
} | ||
|
||
if ( session.getFetchGraphLoadContext() != fetchGraphContext ) { | ||
session.setFetchGraphLoadContext( fetchGraphContext ); | ||
} | ||
} | ||
finally { | ||
// HHH-14097 | ||
// Fetch entity graph should be applied only once on top level (for root hydrated object) | ||
// e.g., see org.hibernate.loader.Loader for details | ||
session.setFetchGraphLoadContext( null ); | ||
|
||
} | ||
} | ||
|
||
public static void initializeEntityFromEntityEntryLoadedState( | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The above content was copied from v6's counterpart. Thought the basic explanation of the two types of entity graph modes is supposed to exist in v5 as well.
Given the content has existed in v6 already, we don't need to bother merging this part to v6 as well.