private void writeEntityReferenceFetches(EntityReference entityReference, int depth, PrintWriter printWriter) { if ( BidirectionalEntityReference.class.isInstance( entityReference ) ) { return; } if ( entityReference.getIdentifierDescription().hasFetches() ) { printWriter.println( TreePrinterHelper.INSTANCE.generateNodePrefix( depth ) + "(entity id) " ); writeFetches( ( (FetchSource) entityReference.getIdentifierDescription() ).getFetches(), depth+1, printWriter ); } writeFetches( entityReference.getFetches(), depth, printWriter ); }
@Override public BidirectionalEntityReference[] getBidirectionalEntityReferences() { return targetEntityReference.getBidirectionalEntityReferences(); }
private String extractDetails(EntityReference entityReference) { return String.format( "%s(entity=%s, querySpaceUid=%s, path=%s)", entityReference.getClass().getSimpleName(), entityReference.getEntityPersister().getEntityName(), entityReference.getQuerySpaceUid(), entityReference.getPropertyPath().getFullPath() ); }
@Override public EntityPersister getEntityPersister() { return targetEntityReference.getEntityPersister(); }
private void createSubselects() { if ( subselectLoadableEntityKeyMap == null || nRowsRead <= 1 ) { LOG.tracef( "Skipping create subselects because there are fewer than 2 results, so query by key is more efficient.", getClass().getName() ); return; // early return } final Map<String, int[]> namedParameterLocMap = ResultSetProcessorHelper.buildNamedParameterLocMap( queryParameters, namedParameterContext ); final String subselectQueryString = SubselectFetch.createSubselectFetchQueryFragment( queryParameters ); for ( Map.Entry<EntityReference, Set<EntityKey>> entry : subselectLoadableEntityKeyMap.entrySet() ) { if ( ! entry.getKey().getEntityPersister().hasSubselectLoadableCollections() ) { continue; } SubselectFetch subselectFetch = new SubselectFetch( subselectQueryString, aliasResolutionContext.resolveSqlTableAliasFromQuerySpaceUid( entry.getKey().getQuerySpaceUid() ), (Loadable) entry.getKey().getEntityPersister(), queryParameters, entry.getValue(), namedParameterLocMap ); for ( EntityKey key : entry.getValue() ) { session.getPersistenceContext().getBatchFetchQueue().addSubselect( key, subselectFetch ); } } }
@Override public Fetch[] getFetches() { return targetEntityReference.getFetches(); }
@Override public void startingEntityIdentifier(EntityIdentifierDefinition entityIdentifierDefinition) { log.tracef( "%s Starting entity identifier : %s", StringHelper.repeat( ">>", fetchSourceStack.size() ), entityIdentifierDefinition.getEntityDefinition().getEntityPersister().getEntityName() ); final EntityReference entityReference = (EntityReference) currentSource(); // perform some stack validation if ( ! entityReference.getEntityPersister().equals( entityIdentifierDefinition.getEntityDefinition().getEntityPersister() ) ) { throw new WalkingException( String.format( "Encountered unexpected fetch owner [%s] in stack while processing entity identifier for [%s]", entityReference.getEntityPersister().getEntityName(), entityIdentifierDefinition.getEntityDefinition().getEntityPersister().getEntityName() ) ); } if ( ExpandingEntityIdentifierDescription.class.isInstance( entityReference.getIdentifierDescription() ) ) { pushToStack( (ExpandingEntityIdentifierDescription) entityReference.getIdentifierDescription() ); } }
@Override public EntityIdentifierDescription getIdentifierDescription() { return targetEntityReference.getIdentifierDescription(); } }
@Override public String getQuerySpaceUid() { return targetEntityReference.getQuerySpaceUid(); }
private void checkPoppedEntity(ExpandingFetchSource fetchSource, EntityDefinition entityDefinition) { // make sure what we just fetchSource represents entityDefinition if ( ! EntityReference.class.isInstance( fetchSource ) ) { throw new WalkingException( String.format( "Mismatched FetchSource from stack on pop. Expecting EntityReference(%s), but found %s", entityDefinition.getEntityPersister().getEntityName(), fetchSource ) ); } final EntityReference entityReference = (EntityReference) fetchSource; // NOTE : this is not the most exhaustive of checks because of hierarchical associations (employee/manager) if ( ! entityReference.getEntityPersister().equals( entityDefinition.getEntityPersister() ) ) { throw new WalkingException( "Mismatched FetchSource from stack on pop" ); } }
@Override protected void applyRootReturnSelectFragments(SelectStatementBuilder selectStatementBuilder) { if ( getRootCollectionReturn().allowIndexJoin() && getQueryableCollection().getIndexType().isEntityType() ) { final EntityReference indexEntityReference = getRootCollectionReturn().getIndexGraph().resolveEntityReference(); final EntityReferenceAliases indexEntityReferenceAliases = getAliasResolutionContext().resolveEntityReferenceAliases( indexEntityReference.getQuerySpaceUid() ); selectStatementBuilder.appendSelectClauseFragment( ( (OuterJoinLoadable) indexEntityReference.getEntityPersister() ).selectFragment( indexEntityReferenceAliases.getTableAlias(), indexEntityReferenceAliases.getColumnAliases().getSuffix() ) ); } }
@Test public void testCollectionInitializerCase() { CollectionPersister cp = sessionFactory().getCollectionPersister( Poster.class.getName() + ".messages" ); FetchStyleLoadPlanBuildingAssociationVisitationStrategy strategy = new FetchStyleLoadPlanBuildingAssociationVisitationStrategy( sessionFactory(), LoadQueryInfluencers.NONE, LockMode.NONE ); LoadPlan plan = MetamodelDrivenLoadPlanBuilder.buildRootCollectionLoadPlan( strategy, cp ); assertFalse( plan.hasAnyScalarReturns() ); assertEquals( 1, plan.getReturns().size() ); Return rtn = plan.getReturns().get( 0 ); CollectionReturn collectionReturn = ExtraAssertions.assertTyping( CollectionReturn.class, rtn ); assertNotNull( collectionReturn.getElementGraph() ); assertNotNull( collectionReturn.getElementGraph().getFetches() ); // the collection Message elements are fetched, but Message.poster is not fetched // (because that collection is owned by that Poster) assertEquals( 0, collectionReturn.getElementGraph().getFetches().length ); EntityReference entityReference = ExtraAssertions.assertTyping( EntityReference.class, collectionReturn.getElementGraph() ); assertNotNull( entityReference.getFetches() ); assertEquals( 0, entityReference.getFetches().length ); LoadPlanTreePrinter.INSTANCE.logTree( plan, new AliasResolutionContextImpl( sessionFactory() ) ); }
if ( entityReference.getEntityPersister().getEntityKeyDefinition() != entityIdentifierDefinition ) { throw new WalkingException( String.format( "Encountered unexpected fetch owner [%s] in stack while processing entity identifier for [%s]", entityReference.getEntityPersister().getEntityName(), entityIdentifierDefinition.getEntityDefinition().getEntityPersister().getEntityName() if ( entityReference.getIdentifierDescription() != identifierDescription ) { throw new WalkingException( String.format( "Encountered unexpected fetch owner [%s] in stack while processing entity identifier for [%s]", entityReference.getEntityPersister().getEntityName(), entityIdentifierDefinition.getEntityDefinition().getEntityPersister().getEntityName()
public FetchStats processFetches( FetchSource fetchSource, SelectStatementBuilder selectStatementBuilder, ReaderCollector readerCollector) { final FetchStatsImpl fetchStats = new FetchStatsImpl(); // if the fetchSource is an entityReference, we should also walk its identifier fetches here... // // 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; }
private EntityReferenceAliases getElementEntityReferenceAliases() { return getAliasResolutionContext().resolveEntityReferenceAliases( getElementEntityReference().getQuerySpaceUid() ); }
/** * Read the identifier state for the entity reference for the currently processing row in the ResultSet * * @param resultSet The ResultSet being processed * @param context The processing context * * @return The hydrated state * * @throws java.sql.SQLException Indicates a problem accessing the ResultSet */ private Object readIdentifierHydratedState(ResultSet resultSet, ResultSetProcessingContext context) throws SQLException { try { return entityReference.getEntityPersister().getIdentifierType().hydrate( resultSet, entityReferenceAliases.getColumnAliases().getSuffixedKeyAliases(), context.getSession(), null ); } catch (Exception e) { throw new HibernateException( "Encountered problem trying to hydrate identifier for entity [" + entityReference.getEntityPersister() + "]", e ); } }
final EntityReference indexEntityReference = rootReturn.getIndexGraph().resolveEntityReference(); final EntityReferenceAliases indexEntityReferenceAliases = aliasResolutionContext.generateEntityReferenceAliases( indexEntityReference.getQuerySpaceUid(), indexEntityReference.getEntityPersister() ); readerCollector.add(
private void resolveEntityKey( ResultSet resultSet, ResultSetProcessingContextImpl context, EntityReferenceInitializer entityReferenceInitializer) throws SQLException { final EntityReference entityReference = entityReferenceInitializer.getEntityReference(); final EntityIdentifierDescription identifierDescription = entityReference.getIdentifierDescription(); if ( identifierDescription.hasFetches() || identifierDescription.hasBidirectionalEntityReferences() ) { resolveEntityKey( resultSet, context, (FetchSource) identifierDescription ); } entityReferenceInitializer.resolveEntityKey( resultSet, context ); }
@Override protected void applyRootReturnTableFragments(SelectStatementBuilder selectStatementBuilder) { final OuterJoinLoadable elementOuterJoinLoadable = (OuterJoinLoadable) getElementEntityReference().getEntityPersister(); //final String tableAlias = getCollectionReferenceAliases().getCollectionTableAlias(); final String tableAlias = getElementEntityReferenceAliases().getTableAlias(); final String fragment = elementOuterJoinLoadable.fromTableFragment( tableAlias ) + elementOuterJoinLoadable.fromJoinFragment( tableAlias, true, true); selectStatementBuilder.appendFromClauseFragment( fragment ); }
final Type identifierType = entityReference.getEntityPersister().getIdentifierType(); final Serializable resolvedId = (Serializable) identifierType.resolve( identifierHydratedForm, if ( resolvedId != null ) { processingState.registerEntityKey( context.getSession().generateEntityKey( resolvedId, entityReference.getEntityPersister() ) );