use of org.hibernate.loader.plan.spi.FetchSource in project hibernate-orm by hibernate.
the class AbstractLoadPlanBuildingAssociationVisitationStrategy method foundCircularAssociation.
@Override
public void foundCircularAssociation(AssociationAttributeDefinition attributeDefinition) {
final FetchStrategy fetchStrategy = determineFetchStrategy(attributeDefinition);
if (fetchStrategy.getStyle() != FetchStyle.JOIN) {
// nothing to do
return;
}
final AssociationKey associationKey = attributeDefinition.getAssociationKey();
// go ahead and build the bidirectional fetch
if (attributeDefinition.getAssociationNature() == AssociationAttributeDefinition.AssociationNature.ENTITY) {
final Joinable currentEntityPersister = (Joinable) currentSource().resolveEntityReference().getEntityPersister();
final AssociationKey currentEntityReferenceAssociationKey = new AssociationKey(currentEntityPersister.getTableName(), currentEntityPersister.getKeyColumnNames());
// if associationKey is equal to currentEntityReferenceAssociationKey
// that means that the current EntityPersister has a single primary key attribute
// (i.e., derived attribute) which is mapped by attributeDefinition.
// This is not a bidirectional association.
// TODO: AFAICT, to avoid an overflow, the associated entity must already be loaded into the session, or
// it must be loaded when the ID for the dependent entity is resolved. Is there some other way to
// deal with this???
final FetchSource registeredFetchSource = registeredFetchSource(associationKey);
if (registeredFetchSource != null && !associationKey.equals(currentEntityReferenceAssociationKey)) {
currentSource().buildBidirectionalEntityReference(attributeDefinition, fetchStrategy, registeredFetchSource(associationKey).resolveEntityReference());
}
} else {
// Do nothing for collection
}
}
use of org.hibernate.loader.plan.spi.FetchSource in project hibernate-orm by hibernate.
the class AbstractLoadPlanBuildingAssociationVisitationStrategy method finishingEntity.
@Override
public void finishingEntity(EntityDefinition entityDefinition) {
// Only process the entityDefinition if it is for the root return.
final FetchSource currentSource = currentSource();
final boolean isRoot = EntityReturn.class.isInstance(currentSource) && entityDefinition.getEntityPersister().equals(EntityReturn.class.cast(currentSource).getEntityPersister());
if (!isRoot) {
// if not, this call should represent a fetch which will be handled in #finishingAttribute
return;
}
// if we get here, it is a root
final ExpandingFetchSource popped = popFromStack();
checkPoppedEntity(popped, entityDefinition);
log.tracef("%s Finished root entity : %s", StringHelper.repeat("<<", fetchSourceStack.size()), entityDefinition.getEntityPersister().getEntityName());
}
use of org.hibernate.loader.plan.spi.FetchSource in project hibernate-orm by hibernate.
the class LoadQueryJoinAndFetchProcessor method processFetches.
public FetchStats processFetches(FetchSource fetchSource, SelectStatementBuilder selectStatementBuilder, ReaderCollector readerCollector) {
final FetchStatsImpl fetchStats = new FetchStatsImpl();
// what if fetchSource is a composite fetch (as it would be in the case of a key-many-to-one)?
if (EntityReference.class.isInstance(fetchSource)) {
final EntityReference fetchOwnerAsEntityReference = (EntityReference) fetchSource;
if (fetchOwnerAsEntityReference.getIdentifierDescription().hasFetches()) {
final FetchSource entityIdentifierAsFetchSource = (FetchSource) fetchOwnerAsEntityReference.getIdentifierDescription();
for (Fetch fetch : entityIdentifierAsFetchSource.getFetches()) {
processFetch(selectStatementBuilder, fetchSource, fetch, readerCollector, fetchStats);
}
}
}
processFetches(fetchSource, selectStatementBuilder, readerCollector, fetchStats);
return fetchStats;
}
use of org.hibernate.loader.plan.spi.FetchSource in project hibernate-orm by hibernate.
the class LoadQueryJoinAndFetchProcessor method processFetch.
private void processFetch(SelectStatementBuilder selectStatementBuilder, FetchSource fetchSource, Fetch fetch, ReaderCollector readerCollector, FetchStatsImpl fetchStats) {
// process fetch even if it is not join fetched
if (EntityFetch.class.isInstance(fetch)) {
final EntityFetch entityFetch = (EntityFetch) fetch;
processEntityFetch(selectStatementBuilder, fetchSource, entityFetch, readerCollector, fetchStats);
} else if (CollectionAttributeFetch.class.isInstance(fetch)) {
final CollectionAttributeFetch collectionFetch = (CollectionAttributeFetch) fetch;
processCollectionFetch(selectStatementBuilder, fetchSource, collectionFetch, readerCollector, fetchStats);
} else {
// but do still need to visit their fetches...
if (FetchSource.class.isInstance(fetch)) {
processFetches((FetchSource) fetch, selectStatementBuilder, readerCollector, fetchStats);
}
}
}
use of org.hibernate.loader.plan.spi.FetchSource in project hibernate-orm by hibernate.
the class LoadQueryJoinAndFetchProcessor method processEntityFetch.
private void processEntityFetch(SelectStatementBuilder selectStatementBuilder, FetchSource fetchSource, EntityFetch fetch, ReaderCollector readerCollector, FetchStatsImpl fetchStats) {
// todo : still need to think through expressing bi-directionality in the new model...
// if ( BidirectionalEntityFetch.class.isInstance( fetch ) ) {
// log.tracef( "Skipping bi-directional entity fetch [%s]", fetch );
// return;
// }
fetchStats.processingFetch(fetch);
if (!FetchStrategyHelper.isJoinFetched(fetch.getFetchStrategy())) {
// not join fetched, so nothing else to do
return;
}
// First write out the SQL SELECT fragments
final Joinable joinable = (Joinable) fetch.getEntityPersister();
EntityReferenceAliases aliases = aliasResolutionContext.resolveEntityReferenceAliases(fetch.getQuerySpaceUid());
// the null arguments here relate to many-to-many fetches
selectStatementBuilder.appendSelectClauseFragment(joinable.selectFragment(null, null, aliases.getTableAlias(), aliases.getColumnAliases().getSuffix(), null, true));
// process its identifier fetches first (building EntityReferenceInitializers for them if needed)
if (fetch.getIdentifierDescription().hasFetches()) {
final FetchSource entityIdentifierAsFetchSource = (FetchSource) fetch.getIdentifierDescription();
for (Fetch identifierFetch : entityIdentifierAsFetchSource.getFetches()) {
processFetch(selectStatementBuilder, fetch, identifierFetch, readerCollector, fetchStats);
}
}
// build an EntityReferenceInitializers for the incoming fetch itself
readerCollector.add(new EntityReferenceInitializerImpl(fetch, aliases));
// then visit each of our (non-identifier) fetches
processFetches(fetch, selectStatementBuilder, readerCollector, fetchStats);
}
Aggregations