From b6fd7bf22379bcb05f4660a62f05520878b3a105 Mon Sep 17 00:00:00 2001 From: Gail Badner Date: Fri, 19 Apr 2013 02:15:59 -0700 Subject: [PATCH] HHH-7841 - Redesign Loader --- .../internal/AbstractEntityLoadQueryImpl.java | 51 +-- .../AbstractJoinableAssociationImpl.java | 118 +++++++ .../internal/AbstractLoadQueryImpl.java | 115 ++++--- .../internal/EntityLoadQueryBuilderImpl.java | 50 +-- .../loader/internal/EntityLoadQueryImpl.java | 25 +- .../internal/JoinableAssociationImpl.java | 303 ------------------ .../LoadQueryAliasResolutionContextImpl.java | 34 +- .../loader/spi/JoinableAssociation.java | 112 ++++++- .../spi/LoadQueryAliasResolutionContext.java | 87 ++++- .../loader/spi/LoadQueryBuilder.java | 14 +- ...tityAssociationResultSetProcessorTest.java | 12 +- ...yWithCollectionResultSetProcessorTest.java | 12 +- .../loader/SimpleResultSetProcessorTest.java | 6 +- 13 files changed, 470 insertions(+), 469 deletions(-) create mode 100644 hibernate-core/src/main/java/org/hibernate/loader/internal/AbstractJoinableAssociationImpl.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/loader/internal/JoinableAssociationImpl.java diff --git a/hibernate-core/src/main/java/org/hibernate/loader/internal/AbstractEntityLoadQueryImpl.java b/hibernate-core/src/main/java/org/hibernate/loader/internal/AbstractEntityLoadQueryImpl.java index f328599990..e9745d860f 100755 --- a/hibernate-core/src/main/java/org/hibernate/loader/internal/AbstractEntityLoadQueryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/internal/AbstractEntityLoadQueryImpl.java @@ -1,10 +1,10 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Middleware LLC. + * distributed under license by Red Hat Inc. * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU @@ -20,7 +20,6 @@ * Free Software Foundation, Inc. * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA - * */ package org.hibernate.loader.internal; import java.util.List; @@ -29,26 +28,28 @@ import org.hibernate.LockOptions; import org.hibernate.MappingException; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.loader.plan.spi.EntityReturn; +import org.hibernate.loader.spi.JoinableAssociation; import org.hibernate.loader.spi.LoadQueryAliasResolutionContext; import org.hibernate.persister.entity.OuterJoinLoadable; import org.hibernate.sql.JoinFragment; import org.hibernate.sql.Select; /** - * Abstract walker for walkers which begin at an entity (criteria - * queries and entity loaders). + * Represents an entity load query for criteria + * queries and entity loaders, used for generating SQL. + * + * This code is based on the SQL generation code originally in + * org.hibernate.loader.AbstractEntityJoinWalker. * * @author Gavin King + * @author Gail Badner */ public abstract class AbstractEntityLoadQueryImpl extends AbstractLoadQueryImpl { private final EntityReturn entityReturn; - public AbstractEntityLoadQueryImpl( - SessionFactoryImplementor factory, - EntityReturn entityReturn, - List associations) { - super( factory, associations ); + public AbstractEntityLoadQueryImpl(EntityReturn entityReturn, List associations) { + super( associations ); this.entityReturn = entityReturn; } @@ -56,8 +57,9 @@ public abstract class AbstractEntityLoadQueryImpl extends AbstractLoadQueryImpl final String whereString, final String orderByString, final LockOptions lockOptions, + final SessionFactoryImplementor factory, final LoadQueryAliasResolutionContext aliasResolutionContext) throws MappingException { - return generateSql( null, whereString, orderByString, "", lockOptions, aliasResolutionContext ); + return generateSql( null, whereString, orderByString, "", lockOptions, factory, aliasResolutionContext ); } private String generateSql( @@ -66,27 +68,30 @@ public abstract class AbstractEntityLoadQueryImpl extends AbstractLoadQueryImpl final String orderBy, final String groupBy, final LockOptions lockOptions, + final SessionFactoryImplementor factory, final LoadQueryAliasResolutionContext aliasResolutionContext) throws MappingException { - JoinFragment ojf = mergeOuterJoins( aliasResolutionContext ); + JoinFragment ojf = mergeOuterJoins( factory, aliasResolutionContext ); // If no projection, then the last suffix should be for the entity return. // TODO: simplify how suffixes are generated/processed. - - Select select = new Select( getDialect() ) + final String entityReturnAlias = resolveEntityReturnAlias( aliasResolutionContext ); + Select select = new Select( factory.getDialect() ) .setLockOptions( lockOptions ) .setSelectClause( projection == null ? getPersister().selectFragment( - getAlias( aliasResolutionContext ), + entityReturnAlias, aliasResolutionContext.resolveEntityColumnAliases( entityReturn ).getSuffix() ) + associationSelectString( aliasResolutionContext ) : projection ) .setFromClause( - getDialect().appendLockHint( lockOptions, getPersister().fromTableFragment( getAlias( aliasResolutionContext ) ) ) + - getPersister().fromJoinFragment( getAlias( aliasResolutionContext), true, true ) + factory.getDialect().appendLockHint( + lockOptions, + getPersister().fromTableFragment( entityReturnAlias ) + ) + getPersister().fromJoinFragment( entityReturnAlias, true, true ) ) .setWhereClause( condition ) .setOuterJoins( @@ -96,7 +101,7 @@ public abstract class AbstractEntityLoadQueryImpl extends AbstractLoadQueryImpl .setOrderByClause( orderBy( orderBy, aliasResolutionContext ) ) .setGroupByClause( groupBy ); - if ( getFactory().getSettings().isCommentsEnabled() ) { + if ( factory.getSettings().isCommentsEnabled() ) { select.setComment( getComment() ); } return select.toStatementString(); @@ -104,17 +109,17 @@ public abstract class AbstractEntityLoadQueryImpl extends AbstractLoadQueryImpl protected String getWhereFragment(LoadQueryAliasResolutionContext aliasResolutionContext) throws MappingException { // here we do not bother with the discriminator. - return getPersister().whereJoinFragment( getAlias( aliasResolutionContext ), true, true ); + return getPersister().whereJoinFragment( resolveEntityReturnAlias( aliasResolutionContext ), true, true ); } - public abstract String getComment(); + protected abstract String getComment(); - public final OuterJoinLoadable getPersister() { + protected final OuterJoinLoadable getPersister() { return (OuterJoinLoadable) entityReturn.getEntityPersister(); } - public final String getAlias(LoadQueryAliasResolutionContext aliasResolutionContext) { - return aliasResolutionContext.resolveEntitySqlTableAlias( entityReturn ); + protected final String resolveEntityReturnAlias(LoadQueryAliasResolutionContext aliasResolutionContext) { + return aliasResolutionContext.resolveEntityTableAlias( entityReturn ); } public String toString() { diff --git a/hibernate-core/src/main/java/org/hibernate/loader/internal/AbstractJoinableAssociationImpl.java b/hibernate-core/src/main/java/org/hibernate/loader/internal/AbstractJoinableAssociationImpl.java new file mode 100644 index 0000000000..74c9c31ad0 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/loader/internal/AbstractJoinableAssociationImpl.java @@ -0,0 +1,118 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.loader.internal; +import java.util.Map; + +import org.hibernate.Filter; +import org.hibernate.MappingException; +import org.hibernate.engine.FetchStyle; +import org.hibernate.loader.PropertyPath; +import org.hibernate.loader.plan.spi.CollectionReference; +import org.hibernate.loader.plan.spi.EntityReference; +import org.hibernate.loader.plan.spi.Fetch; +import org.hibernate.loader.spi.JoinableAssociation; +import org.hibernate.persister.entity.OuterJoinLoadable; +import org.hibernate.sql.JoinType; + +/** + * This class represents a joinable association. + * + * @author Gavin King + * @author Gail Badner + */ +public abstract class AbstractJoinableAssociationImpl implements JoinableAssociation { + private final PropertyPath propertyPath; + private final Fetch currentFetch; + private final EntityReference currentEntityReference; + private final CollectionReference currentCollectionReference; + private final JoinType joinType; + private final String withClause; + private final Map enabledFilters; + private final boolean hasRestriction; + + public AbstractJoinableAssociationImpl( + Fetch currentFetch, + EntityReference currentEntityReference, + CollectionReference currentCollectionReference, + String withClause, + boolean hasRestriction, + Map enabledFilters) throws MappingException { + this.propertyPath = currentFetch.getPropertyPath(); + final OuterJoinLoadable ownerPersister = (OuterJoinLoadable) currentFetch.getOwner().retrieveFetchSourcePersister(); + final int propertyNumber = ownerPersister.getEntityMetamodel().getPropertyIndex( currentFetch.getOwnerPropertyName() ); + final boolean isNullable = ownerPersister.isSubclassPropertyNullable( propertyNumber ); + if ( currentFetch.getFetchStrategy().getStyle() == FetchStyle.JOIN ) { + joinType = isNullable ? JoinType.LEFT_OUTER_JOIN : JoinType.INNER_JOIN; + } + else { + joinType = JoinType.NONE; + } + this.currentFetch = currentFetch; + this.currentEntityReference = currentEntityReference; + this.currentCollectionReference = currentCollectionReference; + this.withClause = withClause; + this.hasRestriction = hasRestriction; + this.enabledFilters = enabledFilters; // needed later for many-to-many/filter application + } + + @Override + public PropertyPath getPropertyPath() { + return propertyPath; + } + + @Override + public JoinType getJoinType() { + return joinType; + } + + @Override + public Fetch getCurrentFetch() { + return currentFetch; + } + + @Override + public EntityReference getCurrentEntityReference() { + return currentEntityReference; + } + + @Override + public CollectionReference getCurrentCollectionReference() { + return currentCollectionReference; + } + + @Override + public boolean hasRestriction() { + return hasRestriction; + } + + @Override + public String getWithClause() { + return withClause; + } + + @Override + public Map getEnabledFilters() { + return enabledFilters; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/loader/internal/AbstractLoadQueryImpl.java b/hibernate-core/src/main/java/org/hibernate/loader/internal/AbstractLoadQueryImpl.java index 83ddbd352a..37e6a8d3d7 100755 --- a/hibernate-core/src/main/java/org/hibernate/loader/internal/AbstractLoadQueryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/internal/AbstractLoadQueryImpl.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -25,7 +25,7 @@ package org.hibernate.loader.internal; import java.util.List; import org.hibernate.MappingException; -import org.hibernate.dialect.Dialect; +import org.hibernate.engine.internal.JoinHelper; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.internal.util.StringHelper; import org.hibernate.loader.CollectionAliases; @@ -41,32 +41,23 @@ import org.hibernate.sql.JoinFragment; import org.hibernate.sql.JoinType; /** - * Walks the metamodel, searching for joins, and collecting - * together information needed by OuterJoinLoader. - * - * @see org.hibernate.loader.OuterJoinLoader - * @author Gavin King, Jon Lipsky + * Represents a generic load query used for generating SQL. + * + * This code is based on the SQL generation code originally in + * org.hibernate.loader.JoinWalker. + * + * @author Gavin King + * @author Jon Lipsky + * @author Gail Badner */ public abstract class AbstractLoadQueryImpl { - private final SessionFactoryImplementor factory; - private final List associations; + private final List associations; - protected AbstractLoadQueryImpl( - SessionFactoryImplementor factory, - List associations) { - this.factory = factory; + protected AbstractLoadQueryImpl(List associations) { this.associations = associations; } - protected SessionFactoryImplementor getFactory() { - return factory; - } - - protected Dialect getDialect() { - return factory.getDialect(); - } - protected String orderBy(final String orderBy, LoadQueryAliasResolutionContext aliasResolutionContext) { return mergeOrderings( orderBy( associations, aliasResolutionContext ), orderBy ); } @@ -86,16 +77,37 @@ public abstract class AbstractLoadQueryImpl { /** * Generate a sequence of LEFT OUTER JOIN clauses for the given associations. */ - protected final JoinFragment mergeOuterJoins(LoadQueryAliasResolutionContext aliasResolutionContext) + protected final JoinFragment mergeOuterJoins(SessionFactoryImplementor factory, LoadQueryAliasResolutionContext aliasResolutionContext) throws MappingException { - JoinFragment joinFragment = getDialect().createOuterJoinFragment(); + JoinFragment joinFragment = factory.getDialect().createOuterJoinFragment(); JoinableAssociation previous = null; for ( JoinableAssociation association : associations ) { + final String rhsAlias = aliasResolutionContext.resolveAssociationRhsTableAlias( association ); + final String[] aliasedLhsColumnNames = aliasResolutionContext.resolveAssociationAliasedLhsColumnNames( + association + ); + final String[] rhsColumnNames = JoinHelper.getRHSColumnNames( association.getAssociationType(), factory ); + final String on = resolveOnCondition( factory, association, aliasResolutionContext ); if ( previous != null && previous.isManyToManyWith( association ) ) { - addManyToManyJoin( joinFragment, association, ( QueryableCollection ) previous.getJoinable(), aliasResolutionContext ); + addManyToManyJoin( + joinFragment, + association, + ( QueryableCollection ) previous.getJoinable(), + rhsAlias, + aliasedLhsColumnNames, + rhsColumnNames, + on + ); } else { - addJoins( joinFragment, association, aliasResolutionContext); + addJoins( + joinFragment, + association, + rhsAlias, + aliasedLhsColumnNames, + rhsColumnNames, + on + ); } previous = association; } @@ -105,14 +117,15 @@ public abstract class AbstractLoadQueryImpl { /** * Get the order by string required for collection fetching */ + // TODO: why is this static? protected static String orderBy( - List associations, + List associations, LoadQueryAliasResolutionContext aliasResolutionContext) throws MappingException { StringBuilder buf = new StringBuilder(); JoinableAssociation previous = null; for ( JoinableAssociation association : associations ) { - final String rhsAlias = aliasResolutionContext.resolveRhsAlias( association ); + final String rhsAlias = aliasResolutionContext.resolveAssociationRhsTableAlias( association ); if ( association.getJoinType() == JoinType.LEFT_OUTER_JOIN ) { // why does this matter? if ( association.getJoinable().isCollection() ) { final QueryableCollection queryableCollection = (QueryableCollection) association.getJoinable(); @@ -198,12 +211,18 @@ public abstract class AbstractLoadQueryImpl { ? null : associations.get( i + 1 ); final Joinable joinable = association.getJoinable(); - final EntityAliases currentEntityAliases = aliasResolutionContext.resolveCurrentEntityAliases( association ); - final CollectionAliases currentCollectionAliases = aliasResolutionContext.resolveCurrentCollectionAliases( association ); + final EntityAliases currentEntityAliases = + association.getCurrentEntityReference() == null ? + null : + aliasResolutionContext.resolveEntityColumnAliases( association.getCurrentEntityReference() ); + final CollectionAliases currentCollectionAliases = + association.getCurrentCollectionReference() == null ? + null : + aliasResolutionContext.resolveCollectionColumnAliases( association.getCurrentCollectionReference() ); final String selectFragment = joinable.selectFragment( next == null ? null : next.getJoinable(), - next == null ? null : aliasResolutionContext.resolveRhsAlias( next ), - aliasResolutionContext.resolveRhsAlias( association ), + next == null ? null : aliasResolutionContext.resolveAssociationRhsTableAlias( next ), + aliasResolutionContext.resolveAssociationRhsTableAlias( association ), currentEntityAliases == null ? null : currentEntityAliases.getSuffix(), currentCollectionAliases == null ? null : currentCollectionAliases.getSuffix(), association.getJoinType()==JoinType.LEFT_OUTER_JOIN @@ -220,15 +239,17 @@ public abstract class AbstractLoadQueryImpl { private void addJoins( JoinFragment joinFragment, JoinableAssociation association, - LoadQueryAliasResolutionContext aliasResolutionContext) throws MappingException { - final String rhsAlias = aliasResolutionContext.resolveRhsAlias( association ); + String rhsAlias, + String[] aliasedLhsColumnNames, + String[] rhsColumnNames, + String on) throws MappingException { joinFragment.addJoin( association.getJoinable().getTableName(), rhsAlias, - aliasResolutionContext.resolveAliasedLhsColumnNames( association ), - association.getRhsColumns(), + aliasedLhsColumnNames, + rhsColumnNames, association.getJoinType(), - resolveOnCondition( association, aliasResolutionContext ) + on ); joinFragment.addJoins( association.getJoinable().fromJoinFragment( rhsAlias, false, true ), @@ -236,20 +257,20 @@ public abstract class AbstractLoadQueryImpl { ); } - private String resolveOnCondition(JoinableAssociation joinableAssociation, - LoadQueryAliasResolutionContext aliasResolutionContext) { + private String resolveOnCondition( + SessionFactoryImplementor factory, + JoinableAssociation joinableAssociation, + LoadQueryAliasResolutionContext aliasResolutionContext) { final String withClause = StringHelper.isEmpty( joinableAssociation.getWithClause() ) ? "" : " and ( " + joinableAssociation.getWithClause() + " )"; - return joinableAssociation.getJoinableType().getOnCondition( - aliasResolutionContext.resolveRhsAlias( joinableAssociation ), + return joinableAssociation.getAssociationType().getOnCondition( + aliasResolutionContext.resolveAssociationRhsTableAlias( joinableAssociation ), factory, joinableAssociation.getEnabledFilters() ) + withClause; } - - /* public void validateJoin(String path) throws MappingException { if ( rhsColumns==null || lhsColumns==null @@ -263,14 +284,14 @@ public abstract class AbstractLoadQueryImpl { JoinFragment outerjoin, JoinableAssociation association, QueryableCollection collection, - LoadQueryAliasResolutionContext aliasResolutionContext) throws MappingException { - final String rhsAlias = aliasResolutionContext.resolveRhsAlias( association ); - final String[] aliasedLhsColumnNames = aliasResolutionContext.resolveAliasedLhsColumnNames( association ); + String rhsAlias, + String[] aliasedLhsColumnNames, + String[] rhsColumnNames, + String on) throws MappingException { final String manyToManyFilter = collection.getManyToManyFilterFragment( rhsAlias, association.getEnabledFilters() ); - final String on = resolveOnCondition( association, aliasResolutionContext ); String condition = "".equals( manyToManyFilter ) ? on : "".equals( on ) @@ -280,7 +301,7 @@ public abstract class AbstractLoadQueryImpl { association.getJoinable().getTableName(), rhsAlias, aliasedLhsColumnNames, - association.getRhsColumns(), + rhsColumnNames, association.getJoinType(), condition ); diff --git a/hibernate-core/src/main/java/org/hibernate/loader/internal/EntityLoadQueryBuilderImpl.java b/hibernate-core/src/main/java/org/hibernate/loader/internal/EntityLoadQueryBuilderImpl.java index 688d1bc9bd..aef90267f1 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/internal/EntityLoadQueryBuilderImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/internal/EntityLoadQueryBuilderImpl.java @@ -40,6 +40,7 @@ import org.hibernate.loader.plan.spi.LoadPlan; import org.hibernate.loader.plan.spi.visit.LoadPlanVisitationStrategyAdapter; import org.hibernate.loader.plan.spi.visit.LoadPlanVisitor; import org.hibernate.loader.plan.spi.Return; +import org.hibernate.loader.spi.JoinableAssociation; import org.hibernate.loader.spi.LoadQueryAliasResolutionContext; import org.hibernate.loader.spi.LoadQueryBuilder; import org.hibernate.persister.entity.OuterJoinLoadable; @@ -49,40 +50,52 @@ import org.hibernate.persister.walking.spi.WalkingException; * @author Gail Badner */ public class EntityLoadQueryBuilderImpl implements LoadQueryBuilder { - private final SessionFactoryImplementor sessionFactory; private final LoadQueryInfluencers loadQueryInfluencers; private final LoadPlan loadPlan; - private final LoadQueryAliasResolutionContext aliasResolutionContext; - private final List associations; + private final List associations; public EntityLoadQueryBuilderImpl( - SessionFactoryImplementor sessionFactory, LoadQueryInfluencers loadQueryInfluencers, - LoadPlan loadPlan, - LoadQueryAliasResolutionContext aliasResolutionContext) { - this.sessionFactory = sessionFactory; + LoadPlan loadPlan) { this.loadQueryInfluencers = loadQueryInfluencers; this.loadPlan = loadPlan; - // TODO: remove reliance on aliasResolutionContext; it should only be needed when generating the SQL. - this.aliasResolutionContext = aliasResolutionContext; + // TODO: the whole point of the following is to build associations. + // this could be done while building loadPlan (and be a part of the LoadPlan). + // Should it be? LocalVisitationStrategy strategy = new LocalVisitationStrategy(); LoadPlanVisitor.visit( loadPlan, strategy ); this.associations = strategy.associations; } @Override - public String generateSql(int batchSize) { - return generateSql( batchSize, getOuterJoinLoadable().getKeyColumnNames() ); + public String generateSql( + int batchSize, + SessionFactoryImplementor sessionFactory, + LoadQueryAliasResolutionContext aliasResolutionContext) { + return generateSql( + batchSize, + getOuterJoinLoadable().getKeyColumnNames(), + sessionFactory, + aliasResolutionContext + ); } - public String generateSql(int batchSize, String[] uniqueKey) { + public String generateSql( + int batchSize, + String[] uniqueKey, + SessionFactoryImplementor sessionFactory, + LoadQueryAliasResolutionContext aliasResolutionContext) { final EntityLoadQueryImpl loadQuery = new EntityLoadQueryImpl( - sessionFactory, getRootEntityReturn(), associations ); - return loadQuery.generateSql( uniqueKey, batchSize, getRootEntityReturn().getLockMode(), aliasResolutionContext ); + return loadQuery.generateSql( + uniqueKey, + batchSize, + getRootEntityReturn().getLockMode(), + sessionFactory, + aliasResolutionContext ); } private EntityReturn getRootEntityReturn() { @@ -92,8 +105,9 @@ public class EntityLoadQueryBuilderImpl implements LoadQueryBuilder { private OuterJoinLoadable getOuterJoinLoadable() { return (OuterJoinLoadable) getRootEntityReturn().getEntityPersister(); } + private class LocalVisitationStrategy extends LoadPlanVisitationStrategyAdapter { - private final List associations = new ArrayList(); + private final List associations = new ArrayList(); private Deque entityReferenceStack = new ArrayDeque(); private Deque collectionReferenceStack = new ArrayDeque(); @@ -135,12 +149,11 @@ public class EntityLoadQueryBuilderImpl implements LoadQueryBuilder { @Override public void startingEntityFetch(EntityFetch entityFetch) { - JoinableAssociationImpl assoc = new JoinableAssociationImpl( + EntityJoinableAssociationImpl assoc = new EntityJoinableAssociationImpl( entityFetch, getCurrentCollectionReference(), "", // getWithClause( entityFetch.getPropertyPath() ) false, // hasRestriction( entityFetch.getPropertyPath() ) - sessionFactory, loadQueryInfluencers.getEnabledFilters() ); associations.add( assoc ); @@ -154,12 +167,11 @@ public class EntityLoadQueryBuilderImpl implements LoadQueryBuilder { @Override public void startingCollectionFetch(CollectionFetch collectionFetch) { - JoinableAssociationImpl assoc = new JoinableAssociationImpl( + CollectionJoinableAssociationImpl assoc = new CollectionJoinableAssociationImpl( collectionFetch, getCurrentEntityReference(), "", // getWithClause( entityFetch.getPropertyPath() ) false, // hasRestriction( entityFetch.getPropertyPath() ) - sessionFactory, loadQueryInfluencers.getEnabledFilters() ); associations.add( assoc ); diff --git a/hibernate-core/src/main/java/org/hibernate/loader/internal/EntityLoadQueryImpl.java b/hibernate-core/src/main/java/org/hibernate/loader/internal/EntityLoadQueryImpl.java index 904ce1c479..148c6126c6 100755 --- a/hibernate-core/src/main/java/org/hibernate/loader/internal/EntityLoadQueryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/internal/EntityLoadQueryImpl.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -30,36 +30,39 @@ import org.hibernate.LockOptions; import org.hibernate.MappingException; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.loader.plan.spi.EntityReturn; +import org.hibernate.loader.spi.JoinableAssociation; import org.hibernate.loader.spi.LoadQueryAliasResolutionContext; /** - * A walker for loaders that fetch entities + * Represents an load query for fetching an entity, used for generating SQL. + * + * This code is based on the SQL generation code originally in + * org.hibernate.loader.EntityJoinWalker. * - * @see org.hibernate.loader.entity.EntityLoader * @author Gavin King + * @author Gail Badner */ public class EntityLoadQueryImpl extends AbstractEntityLoadQueryImpl { public EntityLoadQueryImpl( - final SessionFactoryImplementor factory, EntityReturn entityReturn, - List associations) throws MappingException { - super( factory, entityReturn, associations ); + List associations) throws MappingException { + super( entityReturn, associations ); } public String generateSql( String[] uniqueKey, int batchSize, LockMode lockMode, + SessionFactoryImplementor factory, LoadQueryAliasResolutionContext aliasResolutionContext) { - StringBuilder whereCondition = whereString( getAlias( aliasResolutionContext ), uniqueKey, batchSize ) + StringBuilder whereCondition = whereString( resolveEntityReturnAlias( aliasResolutionContext ), uniqueKey, batchSize ) //include the discriminator and class-level where, but not filters - .append( getPersister().filterFragment( getAlias( aliasResolutionContext ), Collections.EMPTY_MAP ) ); - return generateSql( whereCondition.toString(), "", new LockOptions().setLockMode( lockMode ), aliasResolutionContext ); + .append( getPersister().filterFragment( resolveEntityReturnAlias( aliasResolutionContext ), Collections.EMPTY_MAP ) ); + return generateSql( whereCondition.toString(), "", new LockOptions().setLockMode( lockMode ), factory, aliasResolutionContext ); } - public String getComment() { + protected String getComment() { return "load " + getPersister().getEntityName(); } - } \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/loader/internal/JoinableAssociationImpl.java b/hibernate-core/src/main/java/org/hibernate/loader/internal/JoinableAssociationImpl.java deleted file mode 100644 index b9b07bed56..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/loader/internal/JoinableAssociationImpl.java +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2013, Red Hat Inc. or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Inc. - * - * This copyrighted material is made available to anyone wishing to use, modify, - * copy, or redistribute it subject to the terms and conditions of the GNU - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.loader.internal; -import java.util.Map; - -import org.hibernate.Filter; -import org.hibernate.MappingException; -import org.hibernate.engine.FetchStyle; -import org.hibernate.engine.internal.JoinHelper; -import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.loader.PropertyPath; -import org.hibernate.loader.plan.spi.CollectionFetch; -import org.hibernate.loader.plan.spi.CollectionReference; -import org.hibernate.loader.plan.spi.EntityFetch; -import org.hibernate.loader.plan.spi.EntityReference; -import org.hibernate.loader.plan.spi.Fetch; -import org.hibernate.loader.spi.JoinableAssociation; -import org.hibernate.persister.collection.QueryableCollection; -import org.hibernate.persister.entity.Joinable; -import org.hibernate.persister.entity.OuterJoinLoadable; -import org.hibernate.sql.JoinType; -import org.hibernate.type.AssociationType; -import org.hibernate.type.EntityType; - -/** - * Part of the Hibernate SQL rendering internals. This class represents - * a joinable association. - * - * @author Gavin King - * @author Gail Badner - */ -public class JoinableAssociationImpl implements JoinableAssociation { - private final PropertyPath propertyPath; - private final Joinable joinable; - private final AssociationType joinableType; - private final String[] rhsColumns; - private final Fetch currentFetch; - private final EntityReference currentEntityReference; - private final CollectionReference currentCollectionReference; - private final JoinType joinType; - private final String withClause; - private final Map enabledFilters; - private final boolean hasRestriction; - - public JoinableAssociationImpl( - EntityFetch entityFetch, - CollectionReference currentCollectionReference, - String withClause, - boolean hasRestriction, - SessionFactoryImplementor factory, - Map enabledFilters) throws MappingException { - this( - entityFetch, - entityFetch.getAssociationType(), - entityFetch, - currentCollectionReference, - withClause, - hasRestriction, - factory, - enabledFilters - ); - } - - public JoinableAssociationImpl( - CollectionFetch collectionFetch, - EntityReference currentEntityReference, - String withClause, - boolean hasRestriction, - SessionFactoryImplementor factory, - Map enabledFilters) throws MappingException { - this( - collectionFetch, - collectionFetch.getCollectionPersister().getCollectionType(), - currentEntityReference, - collectionFetch, - withClause, - hasRestriction, - factory, - enabledFilters - ); - } - - private JoinableAssociationImpl( - Fetch currentFetch, - AssociationType associationType, - EntityReference currentEntityReference, - CollectionReference currentCollectionReference, - String withClause, - boolean hasRestriction, - SessionFactoryImplementor factory, - Map enabledFilters) throws MappingException { - this.propertyPath = currentFetch.getPropertyPath(); - this.joinableType = associationType; - final OuterJoinLoadable ownerPersister = (OuterJoinLoadable) currentFetch.getOwner().retrieveFetchSourcePersister(); - final int propertyNumber = ownerPersister.getEntityMetamodel().getPropertyIndex( currentFetch.getOwnerPropertyName() ); - final boolean isNullable = ownerPersister.isSubclassPropertyNullable( propertyNumber ); - if ( currentFetch.getFetchStrategy().getStyle() == FetchStyle.JOIN ) { - joinType = isNullable ? JoinType.LEFT_OUTER_JOIN : JoinType.INNER_JOIN; - } - else { - joinType = JoinType.NONE; - } - this.joinable = joinableType.getAssociatedJoinable(factory); - this.rhsColumns = JoinHelper.getRHSColumnNames( joinableType, factory ); - this.currentFetch = currentFetch; - this.currentEntityReference = currentEntityReference; - this.currentCollectionReference = currentCollectionReference; - this.withClause = withClause; - this.hasRestriction = hasRestriction; - this.enabledFilters = enabledFilters; // needed later for many-to-many/filter application - } - - - /* - public JoinableAssociationImpl( - EntityFetch entityFetch, - String currentCollectionSuffix, - String withClause, - boolean hasRestriction, - SessionFactoryImplementor factory, - Map enabledFilters, - LoadQueryAliasResolutionContext aliasResolutionContext) throws MappingException { - this.propertyPath = entityFetch.getPropertyPath(); - this.joinableType = entityFetch.getAssociationType(); - // TODO: this is not correct - final EntityPersister fetchSourcePersister = entityFetch.getOwner().retrieveFetchSourcePersister(); - final int propertyNumber = fetchSourcePersister.getEntityMetamodel().getPropertyIndex( entityFetch.getOwnerPropertyName() ); - - if ( EntityReference.class.isInstance( entityFetch.getOwner() ) ) { - this.lhsAlias = aliasResolutionContext.resolveEntitySqlTableAlias( (EntityReference) entityFetch.getOwner() ); - } - else { - throw new NotYetImplementedException( "Cannot determine LHS alias for a FetchOwner that is not an EntityReference." ); - } - final OuterJoinLoadable ownerPersister = (OuterJoinLoadable) entityFetch.getOwner().retrieveFetchSourcePersister(); - this.lhsColumns = JoinHelper.getAliasedLHSColumnNames( - entityFetch.getAssociationType(), lhsAlias, propertyNumber, ownerPersister, factory - ); - this.rhsAlias = aliasResolutionContext.resolveEntitySqlTableAlias( entityFetch ); - - final boolean isNullable = ownerPersister.isSubclassPropertyNullable( propertyNumber ); - if ( entityFetch.getFetchStrategy().getStyle() == FetchStyle.JOIN ) { - joinType = isNullable ? JoinType.LEFT_OUTER_JOIN : JoinType.INNER_JOIN; - } - else { - joinType = JoinType.NONE; - } - this.joinable = joinableType.getAssociatedJoinable(factory); - this.rhsColumns = JoinHelper.getRHSColumnNames( joinableType, factory ); - this.currentEntitySuffix = aliasResolutionContext.resolveEntityColumnAliases( entityFetch ).getSuffix(); - this.currentCollectionSuffix = currentCollectionSuffix; - this.on = joinableType.getOnCondition( rhsAlias, factory, enabledFilters ) - + ( withClause == null || withClause.trim().length() == 0 ? "" : " and ( " + withClause + " )" ); - this.hasRestriction = hasRestriction; - this.enabledFilters = enabledFilters; // needed later for many-to-many/filter application - } - - public JoinableAssociationImpl( - CollectionFetch collectionFetch, - String currentEntitySuffix, - String withClause, - boolean hasRestriction, - SessionFactoryImplementor factory, - Map enabledFilters, - LoadQueryAliasResolutionContext aliasResolutionContext) throws MappingException { - this.propertyPath = collectionFetch.getPropertyPath(); - final CollectionType collectionType = collectionFetch.getCollectionPersister().getCollectionType(); - this.joinableType = collectionType; - // TODO: this is not correct - final EntityPersister fetchSourcePersister = collectionFetch.getOwner().retrieveFetchSourcePersister(); - final int propertyNumber = fetchSourcePersister.getEntityMetamodel().getPropertyIndex( collectionFetch.getOwnerPropertyName() ); - - if ( EntityReference.class.isInstance( collectionFetch.getOwner() ) ) { - this.lhsAlias = aliasResolutionContext.resolveEntitySqlTableAlias( (EntityReference) collectionFetch.getOwner() ); - } - else { - throw new NotYetImplementedException( "Cannot determine LHS alias for a FetchOwner that is not an EntityReference." ); - } - final OuterJoinLoadable ownerPersister = (OuterJoinLoadable) collectionFetch.getOwner().retrieveFetchSourcePersister(); - this.lhsColumns = JoinHelper.getAliasedLHSColumnNames( - collectionType, lhsAlias, propertyNumber, ownerPersister, factory - ); - this.rhsAlias = aliasResolutionContext.resolveCollectionSqlTableAlias( collectionFetch ); - - final boolean isNullable = ownerPersister.isSubclassPropertyNullable( propertyNumber ); - if ( collectionFetch.getFetchStrategy().getStyle() == FetchStyle.JOIN ) { - joinType = isNullable ? JoinType.LEFT_OUTER_JOIN : JoinType.INNER_JOIN; - } - else { - joinType = JoinType.NONE; - } - this.joinable = joinableType.getAssociatedJoinable(factory); - this.rhsColumns = JoinHelper.getRHSColumnNames( joinableType, factory ); - this.currentEntitySuffix = currentEntitySuffix; - this.currentCollectionSuffix = aliasResolutionContext.resolveCollectionColumnAliases( collectionFetch ).getSuffix(); - this.on = joinableType.getOnCondition( rhsAlias, factory, enabledFilters ) - + ( withClause == null || withClause.trim().length() == 0 ? "" : " and ( " + withClause + " )" ); - this.hasRestriction = hasRestriction; - this.enabledFilters = enabledFilters; // needed later for many-to-many/filter application - } - */ - - @Override - public PropertyPath getPropertyPath() { - return propertyPath; - } - - @Override - public JoinType getJoinType() { - return joinType; - } - - @Override - public Fetch getCurrentFetch() { - return currentFetch; - } - - @Override - public EntityReference getCurrentEntityReference() { - return currentEntityReference; - } - - @Override - public CollectionReference getCurrentCollectionReference() { - return currentCollectionReference; - } - - private boolean isOneToOne() { - if ( joinableType.isEntityType() ) { - EntityType etype = (EntityType) joinableType; - return etype.isOneToOne() /*&& etype.isReferenceToPrimaryKey()*/; - } - else { - return false; - } - } - - @Override - public AssociationType getJoinableType() { - return joinableType; - } - - @Override - public boolean isCollection() { - return getJoinableType().isCollectionType(); - } - - @Override - public Joinable getJoinable() { - return joinable; - } - - public boolean hasRestriction() { - return hasRestriction; - } - - @Override - public boolean isManyToManyWith(JoinableAssociation other) { - if ( joinable.isCollection() ) { - QueryableCollection persister = ( QueryableCollection ) joinable; - if ( persister.isManyToMany() ) { - return persister.getElementType() == other.getJoinableType(); - } - } - return false; - } - - @Override - public String[] getRhsColumns() { - return rhsColumns; - } - - @Override - public String getWithClause() { - return withClause; - } - - @Override - public Map getEnabledFilters() { - return enabledFilters; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/loader/internal/LoadQueryAliasResolutionContextImpl.java b/hibernate-core/src/main/java/org/hibernate/loader/internal/LoadQueryAliasResolutionContextImpl.java index 688f57cce5..d829669a29 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/internal/LoadQueryAliasResolutionContextImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/internal/LoadQueryAliasResolutionContextImpl.java @@ -50,6 +50,8 @@ import org.hibernate.persister.entity.OuterJoinLoadable; import org.hibernate.type.EntityType; /** + * Provides aliases that are used by load queries and ResultSet processors. + * * @author Gail Badner */ public class LoadQueryAliasResolutionContextImpl implements LoadQueryAliasResolutionContext { @@ -130,7 +132,7 @@ public class LoadQueryAliasResolutionContextImpl implements LoadQueryAliasResolu } @Override - public String resolveEntitySqlTableAlias(EntityReference entityReference) { + public String resolveEntityTableAlias(EntityReference entityReference) { return getOrGenerateLoadQueryEntityAliases( entityReference ).tableAlias; } @@ -140,7 +142,7 @@ public class LoadQueryAliasResolutionContextImpl implements LoadQueryAliasResolu } @Override - public String resolveCollectionSqlTableAlias(CollectionReference collectionReference) { + public String resolveCollectionTableAlias(CollectionReference collectionReference) { return getOrGenerateLoadQueryCollectionAliases( collectionReference ).tableAlias; } @@ -155,34 +157,20 @@ public class LoadQueryAliasResolutionContextImpl implements LoadQueryAliasResolu } @Override - public String resolveRhsAlias(JoinableAssociation joinableAssociation) { + public String resolveAssociationRhsTableAlias(JoinableAssociation joinableAssociation) { return getOrGenerateJoinAssocationAliases( joinableAssociation ).rhsAlias; } @Override - public String resolveLhsAlias(JoinableAssociation joinableAssociation) { + public String resolveAssociationLhsTableAlias(JoinableAssociation joinableAssociation) { return getOrGenerateJoinAssocationAliases( joinableAssociation ).lhsAlias; } @Override - public String[] resolveAliasedLhsColumnNames(JoinableAssociation joinableAssociation) { + public String[] resolveAssociationAliasedLhsColumnNames(JoinableAssociation joinableAssociation) { return getOrGenerateJoinAssocationAliases( joinableAssociation ).aliasedLhsColumnNames; } - @Override - public EntityAliases resolveCurrentEntityAliases(JoinableAssociation joinableAssociation) { - return joinableAssociation.getCurrentEntityReference() == null ? - null: - resolveEntityColumnAliases( joinableAssociation.getCurrentEntityReference() ); - } - - @Override - public CollectionAliases resolveCurrentCollectionAliases(JoinableAssociation joinableAssociation) { - return joinableAssociation.getCurrentCollectionReference() == null ? - null: - resolveCollectionColumnAliases( joinableAssociation.getCurrentCollectionReference() ); - } - protected SessionFactoryImplementor sessionFactory() { return sessionFactory; } @@ -224,17 +212,17 @@ public class LoadQueryAliasResolutionContextImpl implements LoadQueryAliasResolu final Fetch currentFetch = joinableAssociation.getCurrentFetch(); final String lhsAlias; if ( EntityReference.class.isInstance( currentFetch.getOwner() ) ) { - lhsAlias = resolveEntitySqlTableAlias( (EntityReference) currentFetch.getOwner() ); + lhsAlias = resolveEntityTableAlias( (EntityReference) currentFetch.getOwner() ); } else { throw new NotYetImplementedException( "Cannot determine LHS alias for a FetchOwner that is not an EntityReference yet." ); } final String rhsAlias; if ( EntityReference.class.isInstance( currentFetch ) ) { - rhsAlias = resolveEntitySqlTableAlias( (EntityReference) currentFetch ); + rhsAlias = resolveEntityTableAlias( (EntityReference) currentFetch ); } else if ( CollectionReference.class.isInstance( joinableAssociation.getCurrentFetch() ) ) { - rhsAlias = resolveCollectionSqlTableAlias( (CollectionReference) currentFetch ); + rhsAlias = resolveCollectionTableAlias( (CollectionReference) currentFetch ); } else { throw new NotYetImplementedException( "Cannot determine RHS alis for a fetch that is not an EntityReference or CollectionReference." ); @@ -244,7 +232,7 @@ public class LoadQueryAliasResolutionContextImpl implements LoadQueryAliasResolu final OuterJoinLoadable fetchSourcePersister = (OuterJoinLoadable) currentFetch.getOwner().retrieveFetchSourcePersister(); final int propertyNumber = fetchSourcePersister.getEntityMetamodel().getPropertyIndex( currentFetch.getOwnerPropertyName() ); final String[] aliasedLhsColumnNames = JoinHelper.getAliasedLHSColumnNames( - joinableAssociation.getJoinableType(), + joinableAssociation.getAssociationType(), lhsAlias, propertyNumber, fetchSourcePersister, diff --git a/hibernate-core/src/main/java/org/hibernate/loader/spi/JoinableAssociation.java b/hibernate-core/src/main/java/org/hibernate/loader/spi/JoinableAssociation.java index 5e4355091a..d25098bc72 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/spi/JoinableAssociation.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/spi/JoinableAssociation.java @@ -35,32 +35,138 @@ import org.hibernate.sql.JoinType; import org.hibernate.type.AssociationType; /** + * Represents a joinable (entity or collection) association. + * * @author Gail Badner */ public interface JoinableAssociation { + + /** + * Returns the property path of the association. + * + * @return the property path of the association. + */ PropertyPath getPropertyPath(); + /** + * Returns the type of join used for the association. + * + * @return the type of join used for the association. + * + * @see JoinType + */ JoinType getJoinType(); + /** + * Returns the current association fetch object. + * + * @return the current association fetch object. + * + * @see Fetch + */ Fetch getCurrentFetch(); + /** + * Return the current {@link EntityReference}, or null if none. + *

+ * If {@link #getCurrentFetch()} returns an + * {@link org.hibernate.loader.plan.spi.EntityFetch}, this method will + * return the same object as {@link #getCurrentFetch()}. + *

+ * If {@link #getCurrentFetch()} returns a + * {@link org.hibernate.loader.plan.spi.CollectionFetch} and + * the collection's owner is returned or fetched, this + * method will return the {@link EntityReference} that owns the + * {@link Fetch} returned by {@link #getCurrentFetch()}; + * otherwise this method returns null. + * + * @return the current {@link EntityReference}, or null if none. + * + * @see #getCurrentFetch() + * @see Fetch + * @see org.hibernate.loader.plan.spi.CollectionFetch + * @see org.hibernate.loader.plan.spi.EntityFetch + * @see EntityReference + */ EntityReference getCurrentEntityReference(); + /** + * Return the current {@link CollectionReference}, or null if none. + *

+ * If {@link #getCurrentFetch()} returns a + * {@link org.hibernate.loader.plan.spi.CollectionFetch}, this method + * will return the same object as {@link #getCurrentFetch()}. + *

+ * If {@link #getCurrentFetch()} returns an + * {@link org.hibernate.loader.plan.spi.EntityFetch} that is + * a collection element (or part of a composite collection element), + * and that collection is being returned or fetched, this + * method will return the {@link CollectionReference}; + * otherwise this method returns null. + * + * @return the current {@link CollectionReference}, or null if none. + * + * @see #getCurrentFetch() + * @see Fetch + * @see org.hibernate.loader.plan.spi.EntityFetch + * @see org.hibernate.loader.plan.spi.CollectionFetch + * @see CollectionReference + */ CollectionReference getCurrentCollectionReference(); - AssociationType getJoinableType(); + /** + * Returns the association type. + * + * @return the association type. + * + * @see AssociationType + */ + AssociationType getAssociationType(); + /** + * Return the persister for creating the join for the association. + * + * @return the persister for creating the join for the association. + */ Joinable getJoinable(); + /** + * Is this a collection association? + * + * @return true, if this is a collection association; false otherwise. + */ boolean isCollection(); - public String[] getRhsColumns(); - + /** + * Does this association have a restriction? + * + * @return true if this association has a restriction; false, otherwise. + */ boolean hasRestriction(); + /** + * Does this association have a many-to-many association + * with the specified association? + * + * @param other - the other association. + * @return true, if this association has a many-to-many association + * with the other association; false otherwise. + */ boolean isManyToManyWith(JoinableAssociation other); + /** + * Returns the with clause for this association. + * + * @return the with clause for this association. + */ String getWithClause(); + /** + * Returns the filters that are enabled for this association. + * + * @return the filters that are enabled for this association. + * + * @see Filter + */ Map getEnabledFilters(); } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/spi/LoadQueryAliasResolutionContext.java b/hibernate-core/src/main/java/org/hibernate/loader/spi/LoadQueryAliasResolutionContext.java index c2555bbc54..20672f94e3 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/spi/LoadQueryAliasResolutionContext.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/spi/LoadQueryAliasResolutionContext.java @@ -32,32 +32,70 @@ import org.hibernate.loader.plan.spi.EntityReturn; import org.hibernate.loader.plan.spi.ScalarReturn; /** + * Provides aliases that are used by load queries and ResultSet processors. + * * @author Gail Badner */ public interface LoadQueryAliasResolutionContext { + /** + * Resolve the alias associated with the specified {@link EntityReturn}. + * + * @param entityReturn - the {@link EntityReturn}. + * + * @return the alias associated with the specified {@link EntityReturn}. + */ public String resolveEntityReturnAlias(EntityReturn entityReturn); + /** + * Resolve the alias associated with the specified {@link CollectionReturn}. + * + * @param collectionReturn - the {@link CollectionReturn}. + * + * @return the alias associated with {@link CollectionReturn}. + */ public String resolveCollectionReturnAlias(CollectionReturn collectionReturn); + /** + * Resolve the aliases associated with the specified {@link ScalarReturn}. + * + * @param scalarReturn - the {@link ScalarReturn}. + * + * @return the alias associated with {@link ScalarReturn}. + */ String[] resolveScalarReturnAliases(ScalarReturn scalarReturn); /** - * Retrieve the SQL table alias. + * Resolve the SQL table alias for the specified {@link EntityReference}. * - * @return The SQL table alias + * @param entityReference - the {@link EntityReference}. + * @return The SQL table alias for the specified {@link EntityReference}. */ - String resolveEntitySqlTableAlias(EntityReference entityReference); - - EntityAliases resolveEntityColumnAliases(EntityReference entityReference); - - String resolveCollectionSqlTableAlias(CollectionReference collectionReference); + String resolveEntityTableAlias(EntityReference entityReference); /** - * Returns the description of the aliases in the JDBC ResultSet that identify values "belonging" to the - * this collection. + * Returns the description of the aliases in the JDBC ResultSet that identify values "belonging" to + * an entity. * - * @return The ResultSet alias descriptor for the collection + * @param entityReference - the {@link EntityReference} for the entity. + * + * @return The ResultSet alias descriptor for the {@link EntityReference} + */ + EntityAliases resolveEntityColumnAliases(EntityReference entityReference); + + /** + * Resolve the SQL table alias for the specified {@link CollectionReference}. + * + * @param collectionReference - the {@link CollectionReference}. + * @return The SQL table alias for the specified {@link CollectionReference}. + */ + String resolveCollectionTableAlias(CollectionReference collectionReference); + + /** + * Returns the description of the aliases in the JDBC ResultSet that identify values "belonging" to + * the specified {@link CollectionReference}. + * + * @return The ResultSet alias descriptor for the {@link CollectionReference} */ CollectionAliases resolveCollectionColumnAliases(CollectionReference collectionReference); @@ -69,13 +107,28 @@ public interface LoadQueryAliasResolutionContext { */ EntityAliases resolveCollectionElementColumnAliases(CollectionReference collectionReference); - String resolveRhsAlias(JoinableAssociation joinableAssociation); + /** + * Resolve the table alias on the right-hand-side of the specified association. + * + * @param association - the joinable association. + * + * @return the table alias on the right-hand-side of the specified association. + */ + String resolveAssociationRhsTableAlias(JoinableAssociation association); - String resolveLhsAlias(JoinableAssociation joinableAssociation); + /** + * Resolve the table alias on the left-hand-side of the specified association. + * + * @param association - the joinable association. + * + * @return the table alias on the left-hand-side of the specified association. + */ + String resolveAssociationLhsTableAlias(JoinableAssociation association); - String[] resolveAliasedLhsColumnNames(JoinableAssociation joinableAssociation); - - EntityAliases resolveCurrentEntityAliases(JoinableAssociation joinableAssociation); - - CollectionAliases resolveCurrentCollectionAliases(JoinableAssociation joinableAssociation); + /** + * Resolve the column aliases on the left-hand-side of the specified association. + * @param association - the joinable association + * @return the column aliases on the left-hand-side of the specified association. + */ + String[] resolveAssociationAliasedLhsColumnNames(JoinableAssociation association); } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/spi/LoadQueryBuilder.java b/hibernate-core/src/main/java/org/hibernate/loader/spi/LoadQueryBuilder.java index 773f145ddb..a88548f587 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/spi/LoadQueryBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/spi/LoadQueryBuilder.java @@ -23,10 +23,22 @@ */ package org.hibernate.loader.spi; +import org.hibernate.engine.spi.SessionFactoryImplementor; + /** + * Builds a load query for generating SQL. + * * @author Gail Badner */ public interface LoadQueryBuilder { - String generateSql(int batchSize); + /** + * Generates SQL for the performing the load. + * @param batchSize - the batch size. + * @param factory - the session factory. + * @param aliasResolutionContext - the alias resolution context. + * + * @return the SQL string for performing the load + */ + String generateSql(int batchSize, SessionFactoryImplementor factory, LoadQueryAliasResolutionContext aliasResolutionContext); } diff --git a/hibernate-core/src/test/java/org/hibernate/loader/EntityAssociationResultSetProcessorTest.java b/hibernate-core/src/test/java/org/hibernate/loader/EntityAssociationResultSetProcessorTest.java index d223f9bff0..33c32e0504 100644 --- a/hibernate-core/src/test/java/org/hibernate/loader/EntityAssociationResultSetProcessorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/loader/EntityAssociationResultSetProcessorTest.java @@ -102,12 +102,10 @@ public class EntityAssociationResultSetProcessorTest extends BaseCoreFunctionalT Collections.singletonMap( plan.getReturns().get( 0 ), new String[] { "abc" } ) ); final EntityLoadQueryBuilderImpl queryBuilder = new EntityLoadQueryBuilderImpl( - sessionFactory(), LoadQueryInfluencers.NONE, - plan, - aliasResolutionContext + plan ); - final String sql = queryBuilder.generateSql( 1 ); + final String sql = queryBuilder.generateSql( 1, sessionFactory(), aliasResolutionContext ); final ResultSetProcessorImpl resultSetProcessor = new ResultSetProcessorImpl( plan ); final List results = new ArrayList(); @@ -202,12 +200,10 @@ public class EntityAssociationResultSetProcessorTest extends BaseCoreFunctionalT Collections.singletonMap( plan.getReturns().get( 0 ), new String[] { "abc" } ) ); final EntityLoadQueryBuilderImpl queryBuilder = new EntityLoadQueryBuilderImpl( - sessionFactory(), LoadQueryInfluencers.NONE, - plan, - aliasResolutionContext + plan ); - final String sql = queryBuilder.generateSql( 1 ); + final String sql = queryBuilder.generateSql( 1, sessionFactory(), aliasResolutionContext ); final ResultSetProcessorImpl resultSetProcessor = new ResultSetProcessorImpl( plan ); final List results = new ArrayList(); diff --git a/hibernate-core/src/test/java/org/hibernate/loader/EntityWithCollectionResultSetProcessorTest.java b/hibernate-core/src/test/java/org/hibernate/loader/EntityWithCollectionResultSetProcessorTest.java index 182f145257..da1186e0f6 100644 --- a/hibernate-core/src/test/java/org/hibernate/loader/EntityWithCollectionResultSetProcessorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/loader/EntityWithCollectionResultSetProcessorTest.java @@ -90,12 +90,6 @@ public class EntityWithCollectionResultSetProcessorTest extends BaseCoreFunction session.getTransaction().commit(); session.close(); - session = openSession(); - session.beginTransaction(); - session.get( Person.class, person.id ); - session.getTransaction().commit(); - session.close(); - { final SingleRootReturnLoadPlanBuilderStrategy strategy = new SingleRootReturnLoadPlanBuilderStrategy( sessionFactory(), @@ -109,12 +103,10 @@ public class EntityWithCollectionResultSetProcessorTest extends BaseCoreFunction Collections.singletonMap( plan.getReturns().get( 0 ), new String[] { "abc" } ) ); final EntityLoadQueryBuilderImpl queryBuilder = new EntityLoadQueryBuilderImpl( - sessionFactory(), LoadQueryInfluencers.NONE, - plan, - aliasResolutionContext + plan ); - final String sql = queryBuilder.generateSql( 1 ); + final String sql = queryBuilder.generateSql( 1, sessionFactory(), aliasResolutionContext ); final ResultSetProcessorImpl resultSetProcessor = new ResultSetProcessorImpl( plan ); final List results = new ArrayList(); diff --git a/hibernate-core/src/test/java/org/hibernate/loader/SimpleResultSetProcessorTest.java b/hibernate-core/src/test/java/org/hibernate/loader/SimpleResultSetProcessorTest.java index c9c17a699a..2256b881c1 100644 --- a/hibernate-core/src/test/java/org/hibernate/loader/SimpleResultSetProcessorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/loader/SimpleResultSetProcessorTest.java @@ -92,12 +92,10 @@ public class SimpleResultSetProcessorTest extends BaseCoreFunctionalTestCase { Collections.singletonMap( plan.getReturns().get( 0 ), new String[] { "abc" } ) ); final EntityLoadQueryBuilderImpl queryBuilder = new EntityLoadQueryBuilderImpl( - sessionFactory(), LoadQueryInfluencers.NONE, - plan, - aliasResolutionContext + plan ); - final String sql = queryBuilder.generateSql( 1 ); + final String sql = queryBuilder.generateSql( 1, sessionFactory(), aliasResolutionContext ); final ResultSetProcessorImpl resultSetProcessor = new ResultSetProcessorImpl( plan ); final List results = new ArrayList();