HHH-7841 - Redesign Loader

This commit is contained in:
Gail Badner 2013-04-18 13:17:29 -07:00
parent 0416d3f24a
commit f3298620ee
37 changed files with 953 additions and 650 deletions

View File

@ -29,6 +29,7 @@ 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.LoadQueryAliasResolutionContext;
import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.sql.JoinFragment;
import org.hibernate.sql.Select;
@ -54,8 +55,9 @@ public abstract class AbstractEntityLoadQueryImpl extends AbstractLoadQueryImpl
protected final String generateSql(
final String whereString,
final String orderByString,
final LockOptions lockOptions) throws MappingException {
return generateSql( null, whereString, orderByString, "", lockOptions );
final LockOptions lockOptions,
final LoadQueryAliasResolutionContext aliasResolutionContext) throws MappingException {
return generateSql( null, whereString, orderByString, "", lockOptions, aliasResolutionContext );
}
private String generateSql(
@ -63,9 +65,10 @@ public abstract class AbstractEntityLoadQueryImpl extends AbstractLoadQueryImpl
final String condition,
final String orderBy,
final String groupBy,
final LockOptions lockOptions) throws MappingException {
final LockOptions lockOptions,
final LoadQueryAliasResolutionContext aliasResolutionContext) throws MappingException {
JoinFragment ojf = mergeOuterJoins();
JoinFragment ojf = mergeOuterJoins( aliasResolutionContext );
// If no projection, then the last suffix should be for the entity return.
// TODO: simplify how suffixes are generated/processed.
@ -75,19 +78,22 @@ public abstract class AbstractEntityLoadQueryImpl extends AbstractLoadQueryImpl
.setLockOptions( lockOptions )
.setSelectClause(
projection == null ?
getPersister().selectFragment( getAlias(), entityReturn.getEntityAliases().getSuffix() ) + associationSelectString() :
getPersister().selectFragment(
getAlias( aliasResolutionContext ),
aliasResolutionContext.resolveEntityColumnAliases( entityReturn ).getSuffix()
) + associationSelectString( aliasResolutionContext ) :
projection
)
.setFromClause(
getDialect().appendLockHint( lockOptions, getPersister().fromTableFragment( getAlias() ) ) +
getPersister().fromJoinFragment( getAlias(), true, true )
getDialect().appendLockHint( lockOptions, getPersister().fromTableFragment( getAlias( aliasResolutionContext ) ) ) +
getPersister().fromJoinFragment( getAlias( aliasResolutionContext), true, true )
)
.setWhereClause( condition )
.setOuterJoins(
ojf.toFromFragmentString(),
ojf.toWhereFragmentString() + getWhereFragment()
ojf.toWhereFragmentString() + getWhereFragment( aliasResolutionContext )
)
.setOrderByClause( orderBy( orderBy ) )
.setOrderByClause( orderBy( orderBy, aliasResolutionContext ) )
.setGroupByClause( groupBy );
if ( getFactory().getSettings().isCommentsEnabled() ) {
@ -96,9 +102,9 @@ public abstract class AbstractEntityLoadQueryImpl extends AbstractLoadQueryImpl
return select.toStatementString();
}
protected String getWhereFragment() throws MappingException {
protected String getWhereFragment(LoadQueryAliasResolutionContext aliasResolutionContext) throws MappingException {
// here we do not bother with the discriminator.
return getPersister().whereJoinFragment( getAlias(), true, true );
return getPersister().whereJoinFragment( getAlias( aliasResolutionContext ), true, true );
}
public abstract String getComment();
@ -107,8 +113,8 @@ public abstract class AbstractEntityLoadQueryImpl extends AbstractLoadQueryImpl
return (OuterJoinLoadable) entityReturn.getEntityPersister();
}
public final String getAlias() {
return entityReturn.getSqlTableAlias();
public final String getAlias(LoadQueryAliasResolutionContext aliasResolutionContext) {
return aliasResolutionContext.resolveEntitySqlTableAlias( entityReturn );
}
public String toString() {

View File

@ -27,6 +27,11 @@ import java.util.List;
import org.hibernate.MappingException;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.loader.CollectionAliases;
import org.hibernate.loader.EntityAliases;
import org.hibernate.loader.spi.JoinableAssociation;
import org.hibernate.loader.spi.LoadQueryAliasResolutionContext;
import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.persister.entity.Joinable;
import org.hibernate.sql.ConditionFragment;
@ -62,8 +67,8 @@ public abstract class AbstractLoadQueryImpl {
return factory.getDialect();
}
protected String orderBy(final String orderBy) {
return mergeOrderings( orderBy( associations ), orderBy );
protected String orderBy(final String orderBy, LoadQueryAliasResolutionContext aliasResolutionContext) {
return mergeOrderings( orderBy( associations, aliasResolutionContext ), orderBy );
}
protected static String mergeOrderings(String ordering1, String ordering2) {
@ -81,53 +86,56 @@ public abstract class AbstractLoadQueryImpl {
/**
* Generate a sequence of <tt>LEFT OUTER JOIN</tt> clauses for the given associations.
*/
protected final JoinFragment mergeOuterJoins()
protected final JoinFragment mergeOuterJoins(LoadQueryAliasResolutionContext aliasResolutionContext)
throws MappingException {
JoinFragment outerjoin = getDialect().createOuterJoinFragment();
JoinableAssociationImpl last = null;
for ( JoinableAssociationImpl oj : associations ) {
if ( last != null && last.isManyToManyWith( oj ) ) {
oj.addManyToManyJoin( outerjoin, ( QueryableCollection ) last.getJoinable() );
JoinFragment joinFragment = getDialect().createOuterJoinFragment();
JoinableAssociation previous = null;
for ( JoinableAssociation association : associations ) {
if ( previous != null && previous.isManyToManyWith( association ) ) {
addManyToManyJoin( joinFragment, association, ( QueryableCollection ) previous.getJoinable(), aliasResolutionContext );
}
else {
oj.addJoins(outerjoin);
addJoins( joinFragment, association, aliasResolutionContext);
}
last = oj;
previous = association;
}
return outerjoin;
return joinFragment;
}
/**
* Get the order by string required for collection fetching
*/
protected static String orderBy(List<JoinableAssociationImpl> associations)
protected static String orderBy(
List<JoinableAssociationImpl> associations,
LoadQueryAliasResolutionContext aliasResolutionContext)
throws MappingException {
StringBuilder buf = new StringBuilder();
JoinableAssociationImpl last = null;
for ( JoinableAssociationImpl oj : associations ) {
if ( oj.getJoinType() == JoinType.LEFT_OUTER_JOIN ) { // why does this matter?
if ( oj.getJoinable().isCollection() ) {
final QueryableCollection queryableCollection = (QueryableCollection) oj.getJoinable();
JoinableAssociation previous = null;
for ( JoinableAssociation association : associations ) {
final String rhsAlias = aliasResolutionContext.resolveRhsAlias( association );
if ( association.getJoinType() == JoinType.LEFT_OUTER_JOIN ) { // why does this matter?
if ( association.getJoinable().isCollection() ) {
final QueryableCollection queryableCollection = (QueryableCollection) association.getJoinable();
if ( queryableCollection.hasOrdering() ) {
final String orderByString = queryableCollection.getSQLOrderByString( oj.getRHSAlias() );
final String orderByString = queryableCollection.getSQLOrderByString( rhsAlias );
buf.append( orderByString ).append(", ");
}
}
else {
// it might still need to apply a collection ordering based on a
// many-to-many defined order-by...
if ( last != null && last.getJoinable().isCollection() ) {
final QueryableCollection queryableCollection = (QueryableCollection) last.getJoinable();
if ( queryableCollection.isManyToMany() && last.isManyToManyWith( oj ) ) {
if ( previous != null && previous.getJoinable().isCollection() ) {
final QueryableCollection queryableCollection = (QueryableCollection) previous.getJoinable();
if ( queryableCollection.isManyToMany() && previous.isManyToManyWith( association ) ) {
if ( queryableCollection.hasManyToManyOrdering() ) {
final String orderByString = queryableCollection.getManyToManyOrderByString( oj.getRHSAlias() );
final String orderByString = queryableCollection.getManyToManyOrderByString( rhsAlias );
buf.append( orderByString ).append(", ");
}
}
}
}
}
last = oj;
previous = association;
}
if ( buf.length() > 0 ) {
buf.setLength( buf.length() - 2 );
@ -176,7 +184,7 @@ public abstract class AbstractLoadQueryImpl {
/**
* Generate a select list of columns containing all properties of the entity classes
*/
protected final String associationSelectString()
protected final String associationSelectString(LoadQueryAliasResolutionContext aliasResolutionContext)
throws MappingException {
if ( associations.size() == 0 ) {
@ -185,24 +193,100 @@ public abstract class AbstractLoadQueryImpl {
else {
StringBuilder buf = new StringBuilder( associations.size() * 100 );
for ( int i=0; i<associations.size(); i++ ) {
JoinableAssociationImpl join = associations.get(i);
JoinableAssociationImpl next = (i == associations.size() - 1)
JoinableAssociation association = associations.get( i );
JoinableAssociation next = ( i == associations.size() - 1 )
? null
: associations.get( i + 1 );
final Joinable joinable = join.getJoinable();
final Joinable joinable = association.getJoinable();
final EntityAliases currentEntityAliases = aliasResolutionContext.resolveCurrentEntityAliases( association );
final CollectionAliases currentCollectionAliases = aliasResolutionContext.resolveCurrentCollectionAliases( association );
final String selectFragment = joinable.selectFragment(
next == null ? null : next.getJoinable(),
next == null ? null : next.getRHSAlias(),
join.getRHSAlias(),
associations.get( i ).getCurrentEntitySuffix(),
associations.get( i ).getCurrentCollectionSuffix(),
join.getJoinType()==JoinType.LEFT_OUTER_JOIN
next == null ? null : aliasResolutionContext.resolveRhsAlias( next ),
aliasResolutionContext.resolveRhsAlias( association ),
currentEntityAliases == null ? null : currentEntityAliases.getSuffix(),
currentCollectionAliases == null ? null : currentCollectionAliases.getSuffix(),
association.getJoinType()==JoinType.LEFT_OUTER_JOIN
);
if (selectFragment.trim().length() > 0) {
buf.append(", ").append(selectFragment);
// TODO: shouldn't the append of selectFragment be outside this if statement???
buf.append(", ").append( selectFragment );
}
}
return buf.toString();
}
}
}
private void addJoins(
JoinFragment joinFragment,
JoinableAssociation association,
LoadQueryAliasResolutionContext aliasResolutionContext) throws MappingException {
final String rhsAlias = aliasResolutionContext.resolveRhsAlias( association );
joinFragment.addJoin(
association.getJoinable().getTableName(),
rhsAlias,
aliasResolutionContext.resolveAliasedLhsColumnNames( association ),
association.getRhsColumns(),
association.getJoinType(),
resolveOnCondition( association, aliasResolutionContext )
);
joinFragment.addJoins(
association.getJoinable().fromJoinFragment( rhsAlias, false, true ),
association.getJoinable().whereJoinFragment( rhsAlias, false, true )
);
}
private String resolveOnCondition(JoinableAssociation joinableAssociation,
LoadQueryAliasResolutionContext aliasResolutionContext) {
final String withClause = StringHelper.isEmpty( joinableAssociation.getWithClause() ) ?
"" :
" and ( " + joinableAssociation.getWithClause() + " )";
return joinableAssociation.getJoinableType().getOnCondition(
aliasResolutionContext.resolveRhsAlias( joinableAssociation ),
factory,
joinableAssociation.getEnabledFilters()
) + withClause;
}
/*
public void validateJoin(String path) throws MappingException {
if ( rhsColumns==null || lhsColumns==null
|| lhsColumns.length!=rhsColumns.length || lhsColumns.length==0 ) {
throw new MappingException("invalid join columns for association: " + path);
}
}
*/
private void addManyToManyJoin(
JoinFragment outerjoin,
JoinableAssociation association,
QueryableCollection collection,
LoadQueryAliasResolutionContext aliasResolutionContext) throws MappingException {
final String rhsAlias = aliasResolutionContext.resolveRhsAlias( association );
final String[] aliasedLhsColumnNames = aliasResolutionContext.resolveAliasedLhsColumnNames( association );
final String manyToManyFilter = collection.getManyToManyFilterFragment(
rhsAlias,
association.getEnabledFilters()
);
final String on = resolveOnCondition( association, aliasResolutionContext );
String condition = "".equals( manyToManyFilter )
? on
: "".equals( on )
? manyToManyFilter
: on + " and " + manyToManyFilter;
outerjoin.addJoin(
association.getJoinable().getTableName(),
rhsAlias,
aliasedLhsColumnNames,
association.getRhsColumns(),
association.getJoinType(),
condition
);
outerjoin.addJoins(
association.getJoinable().fromJoinFragment( rhsAlias, false, true ),
association.getJoinable().whereJoinFragment( rhsAlias, false, true )
);
}
}

View File

@ -30,16 +30,17 @@ import java.util.List;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.CollectionAliases;
import org.hibernate.loader.EntityAliases;
import org.hibernate.loader.plan.spi.CollectionFetch;
import org.hibernate.loader.plan.spi.CollectionReference;
import org.hibernate.loader.plan.spi.CompositeFetch;
import org.hibernate.loader.plan.spi.EntityFetch;
import org.hibernate.loader.plan.spi.EntityReference;
import org.hibernate.loader.plan.spi.EntityReturn;
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.LoadQueryAliasResolutionContext;
import org.hibernate.loader.spi.LoadQueryBuilder;
import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.persister.walking.spi.WalkingException;
@ -51,15 +52,20 @@ public class EntityLoadQueryBuilderImpl implements LoadQueryBuilder {
private final SessionFactoryImplementor sessionFactory;
private final LoadQueryInfluencers loadQueryInfluencers;
private final LoadPlan loadPlan;
private final LoadQueryAliasResolutionContext aliasResolutionContext;
private final List<JoinableAssociationImpl> associations;
public EntityLoadQueryBuilderImpl(
SessionFactoryImplementor sessionFactory,
LoadQueryInfluencers loadQueryInfluencers,
LoadPlan loadPlan) {
LoadPlan loadPlan,
LoadQueryAliasResolutionContext aliasResolutionContext) {
this.sessionFactory = sessionFactory;
this.loadQueryInfluencers = loadQueryInfluencers;
this.loadPlan = loadPlan;
// TODO: remove reliance on aliasResolutionContext; it should only be needed when generating the SQL.
this.aliasResolutionContext = aliasResolutionContext;
LocalVisitationStrategy strategy = new LocalVisitationStrategy();
LoadPlanVisitor.visit( loadPlan, strategy );
this.associations = strategy.associations;
@ -76,7 +82,7 @@ public class EntityLoadQueryBuilderImpl implements LoadQueryBuilder {
getRootEntityReturn(),
associations
);
return loadQuery.generateSql( uniqueKey, batchSize, getRootEntityReturn().getLockMode() );
return loadQuery.generateSql( uniqueKey, batchSize, getRootEntityReturn().getLockMode(), aliasResolutionContext );
}
private EntityReturn getRootEntityReturn() {
@ -88,8 +94,8 @@ public class EntityLoadQueryBuilderImpl implements LoadQueryBuilder {
}
private class LocalVisitationStrategy extends LoadPlanVisitationStrategyAdapter {
private final List<JoinableAssociationImpl> associations = new ArrayList<JoinableAssociationImpl>();
private Deque<EntityAliases> entityAliasStack = new ArrayDeque<EntityAliases>();
private Deque<CollectionAliases> collectionAliasStack = new ArrayDeque<CollectionAliases>();
private Deque<EntityReference> entityReferenceStack = new ArrayDeque<EntityReference>();
private Deque<CollectionReference> collectionReferenceStack = new ArrayDeque<CollectionReference>();
private EntityReturn entityRootReturn;
@ -110,7 +116,7 @@ public class EntityLoadQueryBuilderImpl implements LoadQueryBuilder {
);
}
this.entityRootReturn = (EntityReturn) rootReturn;
pushToStack( entityAliasStack, entityRootReturn.getEntityAliases() );
pushToStack( entityReferenceStack, entityRootReturn );
}
@Override
@ -124,45 +130,45 @@ public class EntityLoadQueryBuilderImpl implements LoadQueryBuilder {
)
);
}
popFromStack( entityAliasStack, ( (EntityReturn) rootReturn ).getEntityAliases() );
popFromStack( entityReferenceStack, entityRootReturn );
}
@Override
public void startingEntityFetch(EntityFetch entityFetch) {
JoinableAssociationImpl assoc = new JoinableAssociationImpl(
entityFetch,
getCurrentCollectionSuffix(),
getCurrentCollectionReference(),
"", // getWithClause( entityFetch.getPropertyPath() )
false, // hasRestriction( entityFetch.getPropertyPath() )
sessionFactory,
loadQueryInfluencers.getEnabledFilters()
);
associations.add( assoc );
pushToStack( entityAliasStack, entityFetch.getEntityAliases() );
pushToStack( entityReferenceStack, entityFetch );
}
@Override
public void finishingEntityFetch(EntityFetch entityFetch) {
popFromStack( entityAliasStack, entityFetch.getEntityAliases() );
popFromStack( entityReferenceStack, entityFetch );
}
@Override
public void startingCollectionFetch(CollectionFetch collectionFetch) {
JoinableAssociationImpl assoc = new JoinableAssociationImpl(
collectionFetch,
getCurrentEntitySuffix(),
getCurrentEntityReference(),
"", // getWithClause( entityFetch.getPropertyPath() )
false, // hasRestriction( entityFetch.getPropertyPath() )
sessionFactory,
loadQueryInfluencers.getEnabledFilters()
);
associations.add( assoc );
pushToStack( collectionAliasStack, collectionFetch.getCollectionAliases() );
pushToStack( collectionReferenceStack, collectionFetch );
}
@Override
public void finishingCollectionFetch(CollectionFetch collectionFetch) {
popFromStack( collectionAliasStack, collectionFetch.getCollectionAliases() );
popFromStack( collectionReferenceStack, collectionFetch );
}
@Override
@ -177,16 +183,16 @@ public class EntityLoadQueryBuilderImpl implements LoadQueryBuilder {
@Override
public void finish(LoadPlan loadPlan) {
entityAliasStack.clear();
collectionAliasStack.clear();
entityReferenceStack.clear();
collectionReferenceStack.clear();
}
private String getCurrentEntitySuffix() {
return entityAliasStack.peekFirst() == null ? null : entityAliasStack.peekFirst().getSuffix();
private EntityReference getCurrentEntityReference() {
return entityReferenceStack.peekFirst() == null ? null : entityReferenceStack.peekFirst();
}
private String getCurrentCollectionSuffix() {
return collectionAliasStack.peekFirst() == null ? null : collectionAliasStack.peekFirst().getSuffix();
private CollectionReference getCurrentCollectionReference() {
return collectionReferenceStack.peekFirst() == null ? null : collectionReferenceStack.peekFirst();
}
private <T> void pushToStack(Deque<T> stack, T value) {

View File

@ -30,6 +30,7 @@ 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.LoadQueryAliasResolutionContext;
/**
* A walker for loaders that fetch entities
@ -46,11 +47,15 @@ public class EntityLoadQueryImpl extends AbstractEntityLoadQueryImpl {
super( factory, entityReturn, associations );
}
public String generateSql(String[] uniqueKey, int batchSize, LockMode lockMode) {
StringBuilder whereCondition = whereString( getAlias(), uniqueKey, batchSize )
public String generateSql(
String[] uniqueKey,
int batchSize,
LockMode lockMode,
LoadQueryAliasResolutionContext aliasResolutionContext) {
StringBuilder whereCondition = whereString( getAlias( aliasResolutionContext ), uniqueKey, batchSize )
//include the discriminator and class-level where, but not filters
.append( getPersister().filterFragment( getAlias(), Collections.EMPTY_MAP ) );
return generateSql( whereCondition.toString(), "", new LockOptions().setLockMode( lockMode ) );
.append( getPersister().filterFragment( getAlias( aliasResolutionContext ), Collections.EMPTY_MAP ) );
return generateSql( whereCondition.toString(), "", new LockOptions().setLockMode( lockMode ), aliasResolutionContext );
}
public String getComment() {

View File

@ -22,26 +22,25 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.loader.internal;
import java.util.List;
import java.util.Map;
import org.hibernate.Filter;
import org.hibernate.MappingException;
import org.hibernate.cfg.NotYetImplementedException;
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.EntityPersister;
import org.hibernate.persister.entity.Joinable;
import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.sql.JoinFragment;
import org.hibernate.sql.JoinType;
import org.hibernate.type.AssociationType;
import org.hibernate.type.CollectionType;
import org.hibernate.type.EntityType;
/**
@ -51,91 +50,72 @@ import org.hibernate.type.EntityType;
* @author Gavin King
* @author Gail Badner
*/
public final class JoinableAssociationImpl {
public class JoinableAssociationImpl implements JoinableAssociation {
private final PropertyPath propertyPath;
private final AssociationType joinableType;
private final Joinable joinable;
private final String lhsAlias; // belong to other persister
private final String[] lhsColumns; // belong to other persister
private final String rhsAlias;
private final AssociationType joinableType;
private final String[] rhsColumns;
private final String currentEntitySuffix;
private final String currentCollectionSuffix;
private final Fetch currentFetch;
private final EntityReference currentEntityReference;
private final CollectionReference currentCollectionReference;
private final JoinType joinType;
private final String on;
private final Map enabledFilters;
private final String withClause;
private final Map<String, Filter> enabledFilters;
private final boolean hasRestriction;
public JoinableAssociationImpl(
EntityFetch entityFetch,
String currentCollectionSuffix,
CollectionReference currentCollectionReference,
String withClause,
boolean hasRestriction,
SessionFactoryImplementor factory,
Map enabledFilters) 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 = ( (EntityReference) entityFetch.getOwner() ).getSqlTableAlias();
}
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
Map<String, Filter> enabledFilters) throws MappingException {
this(
entityFetch,
entityFetch.getAssociationType(),
entityFetch,
currentCollectionReference,
withClause,
hasRestriction,
factory,
enabledFilters
);
this.rhsAlias = entityFetch.getSqlTableAlias();
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 = entityFetch.getEntityAliases().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,
EntityReference currentEntityReference,
String withClause,
boolean hasRestriction,
SessionFactoryImplementor factory,
Map enabledFilters) 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 = ( (EntityReference) collectionFetch.getOwner() ).getSqlTableAlias();
}
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
Map<String, Filter> enabledFilters) throws MappingException {
this(
collectionFetch,
collectionFetch.getCollectionPersister().getCollectionType(),
currentEntityReference,
collectionFetch,
withClause,
hasRestriction,
factory,
enabledFilters
);
this.rhsAlias = collectionFetch.getAlias();
}
private JoinableAssociationImpl(
Fetch currentFetch,
AssociationType associationType,
EntityReference currentEntityReference,
CollectionReference currentCollectionReference,
String withClause,
boolean hasRestriction,
SessionFactoryImplementor factory,
Map<String, Filter> 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 ( collectionFetch.getFetchStrategy().getStyle() == FetchStyle.JOIN ) {
if ( currentFetch.getFetchStrategy().getStyle() == FetchStyle.JOIN ) {
joinType = isNullable ? JoinType.LEFT_OUTER_JOIN : JoinType.INNER_JOIN;
}
else {
@ -143,36 +123,127 @@ public final class JoinableAssociationImpl {
}
this.joinable = joinableType.getAssociatedJoinable(factory);
this.rhsColumns = JoinHelper.getRHSColumnNames( joinableType, factory );
this.currentEntitySuffix = currentEntitySuffix;
this.currentCollectionSuffix = collectionFetch.getCollectionAliases().getSuffix();
this.on = joinableType.getOnCondition( rhsAlias, factory, enabledFilters )
+ ( withClause == null || withClause.trim().length() == 0 ? "" : " and ( " + withClause + " )" );
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;
}
public String getLhsAlias() {
return lhsAlias;
@Override
public Fetch getCurrentFetch() {
return currentFetch;
}
public String getRHSAlias() {
return rhsAlias;
@Override
public EntityReference getCurrentEntityReference() {
return currentEntityReference;
}
public String getCurrentEntitySuffix() {
return currentEntitySuffix;
}
public String getCurrentCollectionSuffix() {
return currentCollectionSuffix;
@Override
public CollectionReference getCurrentCollectionReference() {
return currentCollectionReference;
}
private boolean isOneToOne() {
@ -185,18 +256,17 @@ public final class JoinableAssociationImpl {
}
}
@Override
public AssociationType getJoinableType() {
return joinableType;
}
public String getRHSUniqueKeyName() {
return joinableType.getRHSUniqueKeyPropertyName();
}
@Override
public boolean isCollection() {
return joinableType.isCollectionType();
return getJoinableType().isCollectionType();
}
@Override
public Joinable getJoinable() {
return joinable;
}
@ -205,54 +275,8 @@ public final class JoinableAssociationImpl {
return hasRestriction;
}
public int getOwner(final List associations) {
if ( isOneToOne() || isCollection() ) {
return getPosition(lhsAlias, associations);
}
else {
return -1;
}
}
/**
* Get the position of the join with the given alias in the
* list of joins
*/
private static int getPosition(String lhsAlias, List associations) {
int result = 0;
for ( int i=0; i<associations.size(); i++ ) {
JoinableAssociationImpl oj = (JoinableAssociationImpl) associations.get(i);
if ( oj.getJoinable().consumesEntityAlias() /*|| oj.getJoinable().consumesCollectionAlias() */ ) {
if ( oj.rhsAlias.equals(lhsAlias) ) return result;
result++;
}
}
return -1;
}
public void addJoins(JoinFragment outerjoin) throws MappingException {
outerjoin.addJoin(
joinable.getTableName(),
rhsAlias,
lhsColumns,
rhsColumns,
joinType,
on
);
outerjoin.addJoins(
joinable.fromJoinFragment(rhsAlias, false, true),
joinable.whereJoinFragment(rhsAlias, false, true)
);
}
public void validateJoin(String path) throws MappingException {
if ( rhsColumns==null || lhsColumns==null
|| lhsColumns.length!=rhsColumns.length || lhsColumns.length==0 ) {
throw new MappingException("invalid join columns for association: " + path);
}
}
public boolean isManyToManyWith(JoinableAssociationImpl other) {
@Override
public boolean isManyToManyWith(JoinableAssociation other) {
if ( joinable.isCollection() ) {
QueryableCollection persister = ( QueryableCollection ) joinable;
if ( persister.isManyToMany() ) {
@ -262,24 +286,18 @@ public final class JoinableAssociationImpl {
return false;
}
public void addManyToManyJoin(JoinFragment outerjoin, QueryableCollection collection) throws MappingException {
String manyToManyFilter = collection.getManyToManyFilterFragment( rhsAlias, enabledFilters );
String condition = "".equals( manyToManyFilter )
? on
: "".equals( on )
? manyToManyFilter
: on + " and " + manyToManyFilter;
outerjoin.addJoin(
joinable.getTableName(),
rhsAlias,
lhsColumns,
rhsColumns,
joinType,
condition
);
outerjoin.addJoins(
joinable.fromJoinFragment(rhsAlias, false, true),
joinable.whereJoinFragment(rhsAlias, false, true)
);
@Override
public String[] getRhsColumns() {
return rhsColumns;
}
@Override
public String getWithClause() {
return withClause;
}
@Override
public Map<String, Filter> getEnabledFilters() {
return enabledFilters;
}
}

View File

@ -0,0 +1,325 @@
/*
* 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.HashMap;
import java.util.Map;
import org.hibernate.cfg.NotYetImplementedException;
import org.hibernate.engine.internal.JoinHelper;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.loader.CollectionAliases;
import org.hibernate.loader.DefaultEntityAliases;
import org.hibernate.loader.EntityAliases;
import org.hibernate.loader.GeneratedCollectionAliases;
import org.hibernate.loader.plan.spi.CollectionReference;
import org.hibernate.loader.plan.spi.CollectionReturn;
import org.hibernate.loader.plan.spi.EntityReference;
import org.hibernate.loader.plan.spi.EntityReturn;
import org.hibernate.loader.plan.spi.Fetch;
import org.hibernate.loader.plan.spi.Return;
import org.hibernate.loader.plan.spi.ScalarReturn;
import org.hibernate.loader.spi.JoinableAssociation;
import org.hibernate.loader.spi.LoadQueryAliasResolutionContext;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Loadable;
import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.type.EntityType;
/**
* @author Gail Badner
*/
public class LoadQueryAliasResolutionContextImpl implements LoadQueryAliasResolutionContext {
private final Map<Return,String[]> aliasesByReturn;
private final Map<EntityReference,LoadQueryEntityAliasesImpl> aliasesByEntityReference =
new HashMap<EntityReference,LoadQueryEntityAliasesImpl>();
private final Map<CollectionReference,LoadQueryCollectionAliasesImpl> aliasesByCollectionReference =
new HashMap<CollectionReference,LoadQueryCollectionAliasesImpl>();
private final Map<JoinableAssociation,JoinableAssociationAliasesImpl> aliasesByJoinableAssociation =
new HashMap<JoinableAssociation, JoinableAssociationAliasesImpl>();
private final SessionFactoryImplementor sessionFactory;
private int currentAliasSuffix = 0;
public LoadQueryAliasResolutionContextImpl(
SessionFactoryImplementor sessionFactory,
int suffixSeed,
Map<Return,String[]> aliasesByReturn) {
this.sessionFactory = sessionFactory;
this.currentAliasSuffix = suffixSeed;
checkAliasesByReturn( aliasesByReturn );
this.aliasesByReturn = new HashMap<Return, String[]>( aliasesByReturn );
}
private static void checkAliasesByReturn(Map<Return, String[]> aliasesByReturn) {
if ( aliasesByReturn == null || aliasesByReturn.size() == 0 ) {
throw new IllegalArgumentException( "No return aliases defined" );
}
for ( Map.Entry<Return,String[]> entry : aliasesByReturn.entrySet() ) {
final Return aReturn = entry.getKey();
final String[] aliases = entry.getValue();
if ( aReturn == null ) {
throw new IllegalArgumentException( "null key found in aliasesByReturn" );
}
if ( aliases == null || aliases.length == 0 ) {
throw new IllegalArgumentException(
String.format( "No alias defined for [%s]", aReturn )
);
}
if ( ( aliases.length > 1 ) &&
( aReturn instanceof EntityReturn || aReturn instanceof CollectionReturn ) ) {
throw new IllegalArgumentException( String.format( "More than 1 alias defined for [%s]", aReturn ) );
}
for ( String alias : aliases ) {
if ( StringHelper.isEmpty( alias ) ) {
throw new IllegalArgumentException( String.format( "An alias for [%s] is null or empty.", aReturn ) );
}
}
}
}
@Override
public String resolveEntityReturnAlias(EntityReturn entityReturn) {
return getAndCheckReturnAliasExists( entityReturn )[ 0 ];
}
@Override
public String resolveCollectionReturnAlias(CollectionReturn collectionReturn) {
return getAndCheckReturnAliasExists( collectionReturn )[ 0 ];
}
@Override
public String[] resolveScalarReturnAliases(ScalarReturn scalarReturn) {
throw new NotYetImplementedException( "Cannot resolve scalar column aliases yet." );
}
private String[] getAndCheckReturnAliasExists(Return aReturn) {
// There is already a check for the appropriate number of aliases stored in aliasesByReturn,
// so just check for existence here.
final String[] aliases = aliasesByReturn.get( aReturn );
if ( aliases == null ) {
throw new IllegalStateException(
String.format( "No alias is defined for [%s]", aReturn )
);
}
return aliases;
}
@Override
public String resolveEntitySqlTableAlias(EntityReference entityReference) {
return getOrGenerateLoadQueryEntityAliases( entityReference ).tableAlias;
}
@Override
public EntityAliases resolveEntityColumnAliases(EntityReference entityReference) {
return getOrGenerateLoadQueryEntityAliases( entityReference ).columnAliases;
}
@Override
public String resolveCollectionSqlTableAlias(CollectionReference collectionReference) {
return getOrGenerateLoadQueryCollectionAliases( collectionReference ).tableAlias;
}
@Override
public CollectionAliases resolveCollectionColumnAliases(CollectionReference collectionReference) {
return getOrGenerateLoadQueryCollectionAliases( collectionReference ).collectionAliases;
}
@Override
public EntityAliases resolveCollectionElementColumnAliases(CollectionReference collectionReference) {
return getOrGenerateLoadQueryCollectionAliases( collectionReference ).collectionElementAliases;
}
@Override
public String resolveRhsAlias(JoinableAssociation joinableAssociation) {
return getOrGenerateJoinAssocationAliases( joinableAssociation ).rhsAlias;
}
@Override
public String resolveLhsAlias(JoinableAssociation joinableAssociation) {
return getOrGenerateJoinAssocationAliases( joinableAssociation ).lhsAlias;
}
@Override
public String[] resolveAliasedLhsColumnNames(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;
}
private String createSuffix() {
return Integer.toString( currentAliasSuffix++ ) + '_';
}
private LoadQueryEntityAliasesImpl getOrGenerateLoadQueryEntityAliases(EntityReference entityReference) {
LoadQueryEntityAliasesImpl aliases = aliasesByEntityReference.get( entityReference );
if ( aliases == null ) {
final EntityPersister entityPersister = entityReference.getEntityPersister();
aliases = new LoadQueryEntityAliasesImpl(
createTableAlias( entityPersister ),
createEntityAliases( entityPersister )
);
aliasesByEntityReference.put( entityReference, aliases );
}
return aliases;
}
private LoadQueryCollectionAliasesImpl getOrGenerateLoadQueryCollectionAliases(CollectionReference collectionReference) {
LoadQueryCollectionAliasesImpl aliases = aliasesByCollectionReference.get( collectionReference );
if ( aliases == null ) {
final CollectionPersister collectionPersister = collectionReference.getCollectionPersister();
aliases = new LoadQueryCollectionAliasesImpl(
createTableAlias( collectionPersister.getRole() ),
createCollectionAliases( collectionPersister ),
createCollectionElementAliases( collectionPersister )
);
aliasesByCollectionReference.put( collectionReference, aliases );
}
return aliases;
}
private JoinableAssociationAliasesImpl getOrGenerateJoinAssocationAliases(JoinableAssociation joinableAssociation) {
JoinableAssociationAliasesImpl aliases = aliasesByJoinableAssociation.get( joinableAssociation );
if ( aliases == null ) {
final Fetch currentFetch = joinableAssociation.getCurrentFetch();
final String lhsAlias;
if ( EntityReference.class.isInstance( currentFetch.getOwner() ) ) {
lhsAlias = resolveEntitySqlTableAlias( (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 );
}
else if ( CollectionReference.class.isInstance( joinableAssociation.getCurrentFetch() ) ) {
rhsAlias = resolveCollectionSqlTableAlias( (CollectionReference) currentFetch );
}
else {
throw new NotYetImplementedException( "Cannot determine RHS alis for a fetch that is not an EntityReference or CollectionReference." );
}
// TODO: can't this be found in CollectionAliases or EntityAliases? should be moved to LoadQueryAliasResolutionContextImpl
final OuterJoinLoadable fetchSourcePersister = (OuterJoinLoadable) currentFetch.getOwner().retrieveFetchSourcePersister();
final int propertyNumber = fetchSourcePersister.getEntityMetamodel().getPropertyIndex( currentFetch.getOwnerPropertyName() );
final String[] aliasedLhsColumnNames = JoinHelper.getAliasedLHSColumnNames(
joinableAssociation.getJoinableType(),
lhsAlias,
propertyNumber,
fetchSourcePersister,
sessionFactory
);
aliases = new JoinableAssociationAliasesImpl( lhsAlias, aliasedLhsColumnNames, rhsAlias );
aliasesByJoinableAssociation.put( joinableAssociation, aliases );
}
return aliases;
}
private String createTableAlias(EntityPersister entityPersister) {
return createTableAlias( StringHelper.unqualifyEntityName( entityPersister.getEntityName() ) );
}
private String createTableAlias(String name) {
return StringHelper.generateAlias( name ) + createSuffix();
}
private EntityAliases createEntityAliases(EntityPersister entityPersister) {
return new DefaultEntityAliases( (Loadable) entityPersister, createSuffix() );
}
private CollectionAliases createCollectionAliases(CollectionPersister collectionPersister) {
return new GeneratedCollectionAliases( collectionPersister, createSuffix() );
}
private EntityAliases createCollectionElementAliases(CollectionPersister collectionPersister) {
if ( !collectionPersister.getElementType().isEntityType() ) {
return null;
}
else {
final EntityType entityElementType = (EntityType) collectionPersister.getElementType();
return createEntityAliases( (EntityPersister) entityElementType.getAssociatedJoinable( sessionFactory() ) );
}
}
private static class LoadQueryEntityAliasesImpl {
private final String tableAlias;
private final EntityAliases columnAliases;
public LoadQueryEntityAliasesImpl(String tableAlias, EntityAliases columnAliases) {
this.tableAlias = tableAlias;
this.columnAliases = columnAliases;
}
}
private static class LoadQueryCollectionAliasesImpl {
private final String tableAlias;
private final CollectionAliases collectionAliases;
private final EntityAliases collectionElementAliases;
public LoadQueryCollectionAliasesImpl(
String tableAlias,
CollectionAliases collectionAliases,
EntityAliases collectionElementAliases) {
this.tableAlias = tableAlias;
this.collectionAliases = collectionAliases;
this.collectionElementAliases = collectionElementAliases;
}
}
private static class JoinableAssociationAliasesImpl {
private final String lhsAlias;
private final String[] aliasedLhsColumnNames;
private final String rhsAlias;
public JoinableAssociationAliasesImpl(
String lhsAlias,
String[] aliasedLhsColumnNames,
String rhsAlias) {
this.lhsAlias = lhsAlias;
this.aliasedLhsColumnNames = aliasedLhsColumnNames;
this.rhsAlias = rhsAlias;
}
}
}

View File

@ -60,6 +60,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.spi.AfterLoadAction;
import org.hibernate.loader.spi.LoadQueryAliasResolutionContext;
import org.hibernate.loader.spi.NamedParameterContext;
import org.hibernate.loader.spi.ResultSetProcessingContext;
import org.hibernate.persister.collection.CollectionPersister;
@ -83,6 +84,7 @@ public class ResultSetProcessingContextImpl implements ResultSetProcessingContex
private final boolean readOnly;
private final QueryParameters queryParameters;
private final NamedParameterContext namedParameterContext;
private final LoadQueryAliasResolutionContext aliasResolutionContext;
private final boolean hadSubselectFetches;
private final EntityKey dictatedRootEntityKey;
@ -100,6 +102,7 @@ public class ResultSetProcessingContextImpl implements ResultSetProcessingContex
boolean useOptionalEntityKey,
QueryParameters queryParameters,
NamedParameterContext namedParameterContext,
LoadQueryAliasResolutionContext aliasResolutionContext,
boolean hadSubselectFetches) {
this.resultSet = resultSet;
this.session = session;
@ -107,6 +110,7 @@ public class ResultSetProcessingContextImpl implements ResultSetProcessingContex
this.readOnly = readOnly;
this.queryParameters = queryParameters;
this.namedParameterContext = namedParameterContext;
this.aliasResolutionContext = aliasResolutionContext;
this.hadSubselectFetches = hadSubselectFetches;
if ( useOptionalEntityKey ) {
@ -192,6 +196,11 @@ public class ResultSetProcessingContextImpl implements ResultSetProcessingContex
);
}
@Override
public LoadQueryAliasResolutionContext getLoadQueryAliasResolutionContext() {
return aliasResolutionContext;
}
@Override
public void checkVersion(
ResultSet resultSet,
@ -300,7 +309,7 @@ public class ResultSetProcessingContextImpl implements ResultSetProcessingContex
checkVersion(
resultSet,
entityKeyContext.getEntityPersister(),
entityKeyContext.getEntityAliases(),
aliasResolutionContext.resolveEntityColumnAliases( entityKeyContext.getEntityReference() ),
entityKey,
existing
);
@ -315,7 +324,7 @@ public class ResultSetProcessingContextImpl implements ResultSetProcessingContex
final String concreteEntityTypeName = getConcreteEntityTypeName(
resultSet,
entityKeyContext.getEntityPersister(),
entityKeyContext.getEntityAliases(),
aliasResolutionContext.resolveEntityColumnAliases( entityKeyContext.getEntityReference() ),
entityKey
);
@ -341,7 +350,7 @@ public class ResultSetProcessingContextImpl implements ResultSetProcessingContex
entityInstance,
concreteEntityTypeName,
entityKey,
entityKeyContext.getEntityAliases(),
aliasResolutionContext.resolveEntityColumnAliases( entityKeyContext.getEntityReference() ),
acquiredLockMode,
entityKeyContext.getEntityPersister(),
true,
@ -476,7 +485,7 @@ public class ResultSetProcessingContextImpl implements ResultSetProcessingContex
null,
null,
rootCollectionReturn.getCollectionPersister(),
rootCollectionReturn.getCollectionAliases(),
aliasResolutionContext.resolveCollectionColumnAliases( rootCollectionReturn ),
resultSet,
session
);
@ -490,7 +499,7 @@ public class ResultSetProcessingContextImpl implements ResultSetProcessingContex
owner,
collectionFetch.getCollectionPersister().getCollectionType().getKeyOfOwner( owner, session ),
collectionFetch.getCollectionPersister(),
collectionFetch.getCollectionAliases(),
aliasResolutionContext.resolveCollectionColumnAliases( collectionFetch ),
resultSet,
session
);

View File

@ -46,6 +46,7 @@ import org.hibernate.loader.plan.spi.visit.LoadPlanVisitor;
import org.hibernate.loader.plan.spi.Return;
import org.hibernate.loader.spi.AfterLoadAction;
import org.hibernate.loader.spi.LoadPlanAdvisor;
import org.hibernate.loader.spi.LoadQueryAliasResolutionContext;
import org.hibernate.loader.spi.NamedParameterContext;
import org.hibernate.loader.spi.ScrollableResultSetProcessor;
import org.hibernate.loader.spi.ResultSetProcessor;
@ -84,6 +85,7 @@ public class ResultSetProcessorImpl implements ResultSetProcessor {
final SessionImplementor session,
QueryParameters queryParameters,
NamedParameterContext namedParameterContext,
LoadQueryAliasResolutionContext aliasResolutionContext,
boolean returnProxies,
boolean readOnly,
ResultTransformer forcedResultTransformer,
@ -115,6 +117,7 @@ public class ResultSetProcessorImpl implements ResultSetProcessor {
false, // use optional entity key? actually for now always say no since in the simple test cases true causes failures because there is no optional key
queryParameters,
namedParameterContext,
aliasResolutionContext,
hadSubselectFetches
);

View File

@ -46,10 +46,8 @@ public class CascadeLoadPlanBuilderStrategy extends SingleRootReturnLoadPlanBuil
public CascadeLoadPlanBuilderStrategy(
CascadingAction cascadeActionToMatch,
SessionFactoryImplementor sessionFactory,
LoadQueryInfluencers loadQueryInfluencers,
String rootAlias,
int suffixSeed) {
super( sessionFactory, loadQueryInfluencers, rootAlias, suffixSeed );
LoadQueryInfluencers loadQueryInfluencers) {
super( sessionFactory, loadQueryInfluencers );
this.cascadeActionToMatch = cascadeActionToMatch;
}

View File

@ -25,8 +25,6 @@ package org.hibernate.loader.plan.internal;
import org.hibernate.LockMode;
import org.hibernate.engine.FetchStrategy;
import org.hibernate.loader.CollectionAliases;
import org.hibernate.loader.EntityAliases;
import org.hibernate.loader.plan.spi.AbstractFetchOwner;
import org.hibernate.loader.plan.spi.CollectionFetch;
import org.hibernate.loader.plan.spi.CompositeFetch;
@ -34,7 +32,6 @@ import org.hibernate.loader.plan.spi.EntityFetch;
import org.hibernate.loader.plan.spi.FetchOwner;
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
import org.hibernate.persister.walking.spi.CollectionDefinition;
import org.hibernate.persister.walking.spi.CompositionDefinition;
/**
@ -46,22 +43,12 @@ public class LoadPlanBuildingHelper {
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy,
LoadPlanBuildingContext loadPlanBuildingContext) {
final CollectionAliases collectionAliases = loadPlanBuildingContext.resolveCollectionColumnAliases( attributeDefinition );
final CollectionDefinition collectionDefinition = attributeDefinition.toCollectionDefinition();
final EntityAliases elementEntityAliases =
collectionDefinition.getElementDefinition().getType().isEntityType() ?
loadPlanBuildingContext.resolveEntityColumnAliases( attributeDefinition ) :
null;
return new CollectionFetch(
loadPlanBuildingContext.getSessionFactory(),
loadPlanBuildingContext.resolveFetchSourceAlias( attributeDefinition ),
LockMode.NONE, // todo : for now
fetchOwner,
fetchStrategy,
attributeDefinition.getName(),
collectionAliases,
elementEntityAliases
attributeDefinition.getName()
);
}
@ -69,18 +56,14 @@ public class LoadPlanBuildingHelper {
FetchOwner fetchOwner,
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy,
String sqlTableAlias,
LoadPlanBuildingContext loadPlanBuildingContext) {
return new EntityFetch(
loadPlanBuildingContext.getSessionFactory(),
loadPlanBuildingContext.resolveFetchSourceAlias( attributeDefinition ),
LockMode.NONE, // todo : for now
fetchOwner,
attributeDefinition.getName(),
fetchStrategy,
sqlTableAlias,
loadPlanBuildingContext.resolveEntityColumnAliases( attributeDefinition )
fetchStrategy
);
}
@ -90,7 +73,6 @@ public class LoadPlanBuildingHelper {
LoadPlanBuildingContext loadPlanBuildingContext) {
return new CompositeFetch(
loadPlanBuildingContext.getSessionFactory(),
loadPlanBuildingContext.resolveFetchSourceAlias( attributeDefinition ),
(AbstractFetchOwner) fetchOwner,
attributeDefinition.getName()
);

View File

@ -31,8 +31,6 @@ import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.loader.CollectionAliases;
import org.hibernate.loader.EntityAliases;
import org.hibernate.loader.PropertyPath;
import org.hibernate.loader.plan.spi.build.AbstractLoadPlanBuilderStrategy;
import org.hibernate.loader.plan.spi.CollectionReturn;
@ -41,12 +39,9 @@ import org.hibernate.loader.plan.spi.LoadPlan;
import org.hibernate.loader.plan.spi.build.LoadPlanBuilderStrategy;
import org.hibernate.loader.plan.spi.Return;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
import org.hibernate.persister.walking.spi.CollectionDefinition;
import org.hibernate.persister.walking.spi.EntityDefinition;
import org.hibernate.type.EntityType;
import org.hibernate.type.Type;
/**
* LoadPlanBuilderStrategy implementation used for building LoadPlans with a single processing RootEntity LoadPlan building.
@ -65,20 +60,15 @@ public class SingleRootReturnLoadPlanBuilderStrategy
private final LoadQueryInfluencers loadQueryInfluencers;
private final String rootAlias;
private Return rootReturn;
private PropertyPath propertyPath = new PropertyPath( "" );
public SingleRootReturnLoadPlanBuilderStrategy(
SessionFactoryImplementor sessionFactory,
LoadQueryInfluencers loadQueryInfluencers,
String rootAlias,
int suffixSeed) {
super( sessionFactory, suffixSeed );
LoadQueryInfluencers loadQueryInfluencers) {
super( sessionFactory );
this.loadQueryInfluencers = loadQueryInfluencers;
this.rootAlias = rootAlias;
}
@Override
@ -139,11 +129,8 @@ public class SingleRootReturnLoadPlanBuilderStrategy
final String entityName = entityDefinition.getEntityPersister().getEntityName();
return new EntityReturn(
sessionFactory(),
rootAlias,
LockMode.NONE, // todo : for now
entityName,
StringHelper.generateAlias( StringHelper.unqualifyEntityName( entityName ), currentDepth() ),
generateEntityColumnAliases( entityDefinition.getEntityPersister() )
entityName
);
}
@ -151,44 +138,11 @@ public class SingleRootReturnLoadPlanBuilderStrategy
protected CollectionReturn buildRootCollectionReturn(CollectionDefinition collectionDefinition) {
final CollectionPersister persister = collectionDefinition.getCollectionPersister();
final String collectionRole = persister.getRole();
final CollectionAliases collectionAliases = generateCollectionColumnAliases(
collectionDefinition.getCollectionPersister()
);
final Type elementType = collectionDefinition.getCollectionPersister().getElementType();
final EntityAliases elementAliases;
if ( elementType.isEntityType() ) {
final EntityType entityElementType = (EntityType) elementType;
elementAliases = generateEntityColumnAliases(
(EntityPersister) entityElementType.getAssociatedJoinable( sessionFactory() )
);
}
else {
elementAliases = null;
}
return new CollectionReturn(
sessionFactory(),
rootAlias,
LockMode.NONE, // todo : for now
persister.getOwnerEntityPersister().getEntityName(),
StringHelper.unqualify( collectionRole ),
collectionAliases,
elementAliases
StringHelper.unqualify( collectionRole )
);
}
// LoadPlanBuildingContext impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public String resolveRootSourceAlias(EntityDefinition definition) {
return rootAlias;
}
@Override
public String resolveRootSourceAlias(CollectionDefinition definition) {
return rootAlias;
}
}

View File

@ -25,8 +25,6 @@ package org.hibernate.loader.plan.spi;
import org.hibernate.LockMode;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.CollectionAliases;
import org.hibernate.loader.EntityAliases;
import org.hibernate.loader.PropertyPath;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.type.Type;
@ -35,34 +33,23 @@ import org.hibernate.type.Type;
* @author Steve Ebersole
*/
public abstract class AbstractCollectionReference extends AbstractPlanNode implements CollectionReference {
private final String alias;
private final LockMode lockMode;
private final CollectionPersister collectionPersister;
private final PropertyPath propertyPath;
private final CollectionAliases collectionAliases;
private final EntityAliases elementEntityAliases;
private final FetchableCollectionIndex indexGraph;
private final FetchableCollectionElement elementGraph;
protected AbstractCollectionReference(
SessionFactoryImplementor sessionFactory,
String alias,
LockMode lockMode,
CollectionPersister collectionPersister,
PropertyPath propertyPath,
CollectionAliases collectionAliases,
EntityAliases elementEntityAliases) {
PropertyPath propertyPath) {
super( sessionFactory );
this.alias = alias;
this.lockMode = lockMode;
this.collectionPersister = collectionPersister;
this.propertyPath = propertyPath;
this.collectionAliases = collectionAliases;
this.elementEntityAliases = elementEntityAliases;
this.indexGraph = buildIndexGraph( getCollectionPersister() );
this.elementGraph = buildElementGraph( getCollectionPersister() );
}
@ -99,14 +86,10 @@ public abstract class AbstractCollectionReference extends AbstractPlanNode imple
protected AbstractCollectionReference(AbstractCollectionReference original, CopyContext copyContext) {
super( original );
this.alias = original.alias;
this.lockMode = original.lockMode;
this.collectionPersister = original.collectionPersister;
this.propertyPath = original.propertyPath;
this.collectionAliases = original.collectionAliases;
this.elementEntityAliases = original.elementEntityAliases;
this.indexGraph = original.indexGraph == null ? null : original.indexGraph.makeCopy( copyContext );
this.elementGraph = original.elementGraph == null ? null : original.elementGraph.makeCopy( copyContext );
}
@ -116,26 +99,11 @@ public abstract class AbstractCollectionReference extends AbstractPlanNode imple
return propertyPath;
}
@Override
public String getAlias() {
return alias;
}
@Override
public LockMode getLockMode() {
return lockMode;
}
@Override
public CollectionAliases getCollectionAliases() {
return collectionAliases;
}
@Override
public EntityAliases getElementEntityAliases() {
return elementEntityAliases;
}
@Override
public CollectionPersister getCollectionPersister() {
return collectionPersister;

View File

@ -27,7 +27,6 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -35,22 +34,17 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
* @author Steve Ebersole
*/
public abstract class AbstractFetchOwner extends AbstractPlanNode implements FetchOwner {
private final String alias;
private final LockMode lockMode;
private List<Fetch> fetches;
public AbstractFetchOwner(SessionFactoryImplementor factory, String alias, LockMode lockMode) {
public AbstractFetchOwner(SessionFactoryImplementor factory, LockMode lockMode) {
super( factory );
this.alias = alias;
this.lockMode = lockMode;
validate();
}
private void validate() {
if ( alias == null ) {
throw new HibernateException( "alias must be specified" );
}
}
/**
@ -60,7 +54,6 @@ public abstract class AbstractFetchOwner extends AbstractPlanNode implements Fet
*/
protected AbstractFetchOwner(AbstractFetchOwner original, CopyContext copyContext) {
super( original );
this.alias = original.alias;
this.lockMode = original.lockMode;
validate();
@ -78,10 +71,6 @@ public abstract class AbstractFetchOwner extends AbstractPlanNode implements Fet
copyContext.getReturnGraphVisitationStrategy().finishingFetches( original );
}
public String getAlias() {
return alias;
}
public LockMode getLockMode() {
return lockMode;
}

View File

@ -42,12 +42,11 @@ public abstract class AbstractSingularAttributeFetch extends AbstractFetchOwner
public AbstractSingularAttributeFetch(
SessionFactoryImplementor factory,
String alias,
LockMode lockMode,
FetchOwner owner,
String ownerProperty,
FetchStrategy fetchStrategy) {
super( factory, alias, lockMode );
super( factory, lockMode );
this.owner = owner;
this.ownerProperty = ownerProperty;
this.fetchStrategy = fetchStrategy;

View File

@ -29,9 +29,8 @@ import java.sql.SQLException;
import org.hibernate.LockMode;
import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.CollectionAliases;
import org.hibernate.loader.EntityAliases;
import org.hibernate.loader.spi.ResultSetProcessingContext;
import org.hibernate.type.CollectionType;
/**
* @author Steve Ebersole
@ -42,27 +41,20 @@ public class CollectionFetch extends AbstractCollectionReference implements Fetc
public CollectionFetch(
SessionFactoryImplementor sessionFactory,
String alias,
LockMode lockMode,
FetchOwner fetchOwner,
FetchStrategy fetchStrategy,
String ownerProperty,
CollectionAliases collectionAliases,
EntityAliases elementEntityAliases) {
String ownerProperty) {
super(
sessionFactory,
alias,
lockMode,
sessionFactory.getCollectionPersister(
fetchOwner.retrieveFetchSourcePersister().getEntityName() + '.' + ownerProperty
),
fetchOwner.getPropertyPath().append( ownerProperty ),
collectionAliases,
elementEntityAliases
fetchOwner.getPropertyPath().append( ownerProperty )
);
this.fetchOwner = fetchOwner;
this.fetchStrategy = fetchStrategy;
fetchOwner.addFetch( this );
}

View File

@ -24,8 +24,6 @@
package org.hibernate.loader.plan.spi;
import org.hibernate.LockMode;
import org.hibernate.loader.CollectionAliases;
import org.hibernate.loader.EntityAliases;
import org.hibernate.loader.PropertyPath;
import org.hibernate.persister.collection.CollectionPersister;
@ -35,12 +33,6 @@ import org.hibernate.persister.collection.CollectionPersister;
* @author Steve Ebersole
*/
public interface CollectionReference {
/**
* Retrieve the alias associated with the persister (entity/collection).
*
* @return The alias
*/
public String getAlias();
/**
* Retrieve the lock mode associated with this return.
@ -63,20 +55,4 @@ public interface CollectionReference {
public PropertyPath getPropertyPath();
public boolean hasEntityElements();
/**
* Returns the description of the aliases in the JDBC ResultSet that identify values "belonging" to the
* this collection.
*
* @return The ResultSet alias descriptor for the collection
*/
public CollectionAliases getCollectionAliases();
/**
* If the elements of this collection are entities, this methods returns the JDBC ResultSet alias descriptions
* for that entity; {@code null} indicates a non-entity collection.
*
* @return The ResultSet alias descriptor for the collection's entity element, or {@code null}
*/
public EntityAliases getElementEntityAliases();
}

View File

@ -28,8 +28,6 @@ import java.sql.SQLException;
import org.hibernate.LockMode;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.CollectionAliases;
import org.hibernate.loader.EntityAliases;
import org.hibernate.loader.PropertyPath;
import org.hibernate.loader.spi.ResultSetProcessingContext;
@ -42,20 +40,14 @@ public class CollectionReturn extends AbstractCollectionReference implements Ret
public CollectionReturn(
SessionFactoryImplementor sessionFactory,
String alias,
LockMode lockMode,
String ownerEntityName,
String ownerProperty,
CollectionAliases collectionAliases,
EntityAliases elementEntityAliases) {
String ownerProperty) {
super(
sessionFactory,
alias,
lockMode,
sessionFactory.getCollectionPersister( ownerEntityName + '.' + ownerProperty ),
new PropertyPath(), // its a root
collectionAliases,
elementEntityAliases
new PropertyPath() // its a root
);
this.ownerEntityName = ownerEntityName;
this.ownerProperty = ownerProperty;

View File

@ -95,13 +95,11 @@ public class CompositeElementGraph extends AbstractPlanNode implements Fetchable
public EntityFetch buildEntityFetch(
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy,
String sqlTableAlias,
LoadPlanBuildingContext loadPlanBuildingContext) {
return LoadPlanBuildingHelper.buildStandardEntityFetch(
this,
attributeDefinition,
fetchStrategy,
sqlTableAlias,
loadPlanBuildingContext
);
}

View File

@ -45,10 +45,9 @@ public class CompositeFetch extends AbstractSingularAttributeFetch {
public CompositeFetch(
SessionFactoryImplementor sessionFactory,
String alias,
FetchOwner owner,
String ownerProperty) {
super( sessionFactory, alias, LockMode.NONE, owner, ownerProperty, FETCH_PLAN );
super( sessionFactory, LockMode.NONE, owner, ownerProperty, FETCH_PLAN );
}
public CompositeFetch(CompositeFetch original, CopyContext copyContext, FetchOwner fetchOwnerCopy) {
@ -72,7 +71,7 @@ public class CompositeFetch extends AbstractSingularAttributeFetch {
public EntityFetch buildEntityFetch(
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy,
String sqlTableAlias, LoadPlanBuildingContext loadPlanBuildingContext) {
LoadPlanBuildingContext loadPlanBuildingContext) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}

View File

@ -94,13 +94,11 @@ public class CompositeIndexGraph extends AbstractPlanNode implements FetchableCo
public EntityFetch buildEntityFetch(
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy,
String sqlTableAlias,
LoadPlanBuildingContext loadPlanBuildingContext) {
return LoadPlanBuildingHelper.buildStandardEntityFetch(
this,
attributeDefinition,
fetchStrategy,
sqlTableAlias,
loadPlanBuildingContext
);
}

View File

@ -7,7 +7,6 @@ import java.util.List;
import org.hibernate.LockMode;
import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.EntityAliases;
import org.hibernate.loader.PropertyPath;
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
@ -67,21 +66,16 @@ public class EntityElementGraph extends AbstractPlanNode implements FetchableCol
copyContext.getReturnGraphVisitationStrategy().finishingFetches( original );
}
@Override
public String getAlias() {
return null;
}
@Override
public String getSqlTableAlias() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public LockMode getLockMode() {
return null;
}
@Override
public EntityReference getEntityReference() {
return this;
}
@Override
public EntityPersister getEntityPersister() {
return elementPersister;
@ -92,11 +86,6 @@ public class EntityElementGraph extends AbstractPlanNode implements FetchableCol
return identifierDescription;
}
@Override
public EntityAliases getEntityAliases() {
return collectionReference.getElementEntityAliases();
}
@Override
public void addFetch(Fetch fetch) {
if ( fetches == null ) {
@ -141,13 +130,11 @@ public class EntityElementGraph extends AbstractPlanNode implements FetchableCol
public EntityFetch buildEntityFetch(
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy,
String sqlTableAlias,
LoadPlanBuildingContext loadPlanBuildingContext) {
return LoadPlanBuildingHelper.buildStandardEntityFetch(
this,
attributeDefinition,
fetchStrategy,
sqlTableAlias,
loadPlanBuildingContext
);
}

View File

@ -32,7 +32,6 @@ import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.EntityAliases;
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
import org.hibernate.loader.spi.ResultSetProcessingContext;
@ -45,8 +44,6 @@ import org.hibernate.type.EntityType;
* @author Steve Ebersole
*/
public class EntityFetch extends AbstractSingularAttributeFetch implements EntityReference {
private final String sqlTableAlias;
private final EntityAliases entityAliases;
private final EntityType associationType;
private final EntityPersister persister;
@ -55,16 +52,11 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit
public EntityFetch(
SessionFactoryImplementor sessionFactory,
String alias,
LockMode lockMode,
FetchOwner owner,
String ownerProperty,
FetchStrategy fetchStrategy,
String sqlTableAlias,
EntityAliases entityAliases) {
super( sessionFactory, alias, lockMode, owner, ownerProperty, fetchStrategy );
this.sqlTableAlias = sqlTableAlias;
this.entityAliases = entityAliases;
FetchStrategy fetchStrategy) {
super( sessionFactory, lockMode, owner, ownerProperty, fetchStrategy );
this.associationType = (EntityType) owner.retrieveFetchSourcePersister().getPropertyType( ownerProperty );
this.persister = sessionFactory.getEntityPersister( associationType.getAssociatedEntityName() );
@ -78,8 +70,6 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit
*/
protected EntityFetch(EntityFetch original, CopyContext copyContext, FetchOwner fetchOwnerCopy) {
super( original, copyContext, fetchOwnerCopy );
this.sqlTableAlias = original.sqlTableAlias;
this.entityAliases = original.entityAliases;
this.associationType = original.associationType;
this.persister = original.persister;
}
@ -88,6 +78,11 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit
return associationType;
}
@Override
public EntityReference getEntityReference() {
return this;
}
@Override
public EntityPersister getEntityPersister() {
return persister;
@ -98,16 +93,6 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit
return identifierDescription;
}
@Override
public String getSqlTableAlias() {
return sqlTableAlias;
}
@Override
public EntityAliases getEntityAliases() {
return entityAliases;
}
@Override
public EntityPersister retrieveFetchSourcePersister() {
return persister;
@ -131,13 +116,11 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit
public EntityFetch buildEntityFetch(
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy,
String sqlTableAlias,
LoadPlanBuildingContext loadPlanBuildingContext) {
return LoadPlanBuildingHelper.buildStandardEntityFetch(
this,
attributeDefinition,
fetchStrategy,
sqlTableAlias,
loadPlanBuildingContext
);
}
@ -224,7 +207,7 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit
context.checkVersion(
resultSet,
persister,
entityAliases,
context.getLoadQueryAliasResolutionContext().resolveEntityColumnAliases( this ),
entityKey,
existing
);
@ -237,7 +220,7 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit
final String concreteEntityTypeName = context.getConcreteEntityTypeName(
resultSet,
persister,
entityAliases,
context.getLoadQueryAliasResolutionContext().resolveEntityColumnAliases( this ),
entityKey
);
@ -258,7 +241,7 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit
entityInstance,
concreteEntityTypeName,
entityKey,
entityAliases,
context.getLoadQueryAliasResolutionContext().resolveEntityColumnAliases( this ),
acquiredLockMode,
persister,
getFetchStrategy().getTiming() == FetchTiming.IMMEDIATE,

View File

@ -30,7 +30,6 @@ import java.util.List;
import org.hibernate.LockMode;
import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.EntityAliases;
import org.hibernate.loader.PropertyPath;
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
@ -88,21 +87,16 @@ public class EntityIndexGraph extends AbstractPlanNode implements FetchableColle
copyContext.getReturnGraphVisitationStrategy().finishingFetches( original );
}
@Override
public String getAlias() {
return null;
}
@Override
public String getSqlTableAlias() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public LockMode getLockMode() {
return null;
}
@Override
public EntityReference getEntityReference() {
return this;
}
@Override
public EntityPersister getEntityPersister() {
return indexPersister;
@ -113,11 +107,6 @@ public class EntityIndexGraph extends AbstractPlanNode implements FetchableColle
return identifierDescription;
}
@Override
public EntityAliases getEntityAliases() {
return null;
}
@Override
public void addFetch(Fetch fetch) {
if ( fetches == null ) {
@ -162,13 +151,11 @@ public class EntityIndexGraph extends AbstractPlanNode implements FetchableColle
public EntityFetch buildEntityFetch(
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy,
String sqlTableAlias,
LoadPlanBuildingContext loadPlanBuildingContext) {
return LoadPlanBuildingHelper.buildStandardEntityFetch(
this,
attributeDefinition,
fetchStrategy,
sqlTableAlias,
loadPlanBuildingContext
);
}

View File

@ -24,7 +24,6 @@
package org.hibernate.loader.plan.spi;
import org.hibernate.LockMode;
import org.hibernate.loader.EntityAliases;
import org.hibernate.loader.spi.ResultSetProcessingContext;
import org.hibernate.persister.entity.EntityPersister;
@ -35,20 +34,6 @@ import org.hibernate.persister.entity.EntityPersister;
*/
public interface EntityReference
extends IdentifierDescriptionInjectable, ResultSetProcessingContext.EntityKeyResolutionContext {
/**
* Retrieve the alias associated with the persister (entity/collection).
*
* @return The alias
*/
public String getAlias();
/**
* Retrieve the SQL table alias.
*
* @return The SQL table alias
*/
public String getSqlTableAlias();
/**
* Retrieve the lock mode associated with this return.
*
@ -64,11 +49,4 @@ public interface EntityReference
public EntityPersister getEntityPersister();
public IdentifierDescription getIdentifierDescription();
/**
* Ugh. *Really* hate this here.
*
* @return
*/
public EntityAliases getEntityAliases();
}

View File

@ -31,7 +31,6 @@ import org.hibernate.LockMode;
import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.EntityAliases;
import org.hibernate.loader.PropertyPath;
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
@ -47,9 +46,6 @@ import static org.hibernate.loader.spi.ResultSetProcessingContext.IdentifierReso
*/
public class EntityReturn extends AbstractFetchOwner implements Return, EntityReference, CopyableReturn {
private final EntityAliases entityAliases;
private final String sqlTableAlias;
private final EntityPersister persister;
private final PropertyPath propertyPath = new PropertyPath(); // its a root
@ -58,40 +54,27 @@ public class EntityReturn extends AbstractFetchOwner implements Return, EntityRe
public EntityReturn(
SessionFactoryImplementor sessionFactory,
String alias,
LockMode lockMode,
String entityName,
String sqlTableAlias,
EntityAliases entityAliases) {
super( sessionFactory, alias, lockMode );
this.entityAliases = entityAliases;
this.sqlTableAlias = sqlTableAlias;
String entityName) {
super( sessionFactory, lockMode );
this.persister = sessionFactory.getEntityPersister( entityName );
}
protected EntityReturn(EntityReturn original, CopyContext copyContext) {
super( original, copyContext );
this.entityAliases = original.entityAliases;
this.sqlTableAlias = original.sqlTableAlias;
this.persister = original.persister;
}
@Override
public String getAlias() {
return super.getAlias();
}
@Override
public String getSqlTableAlias() {
return sqlTableAlias;
}
@Override
public LockMode getLockMode() {
return super.getLockMode();
}
@Override
public EntityReference getEntityReference() {
return this;
}
@Override
public EntityPersister getEntityPersister() {
return persister;
@ -102,11 +85,6 @@ public class EntityReturn extends AbstractFetchOwner implements Return, EntityRe
return identifierDescription;
}
@Override
public EntityAliases getEntityAliases() {
return entityAliases;
}
@Override
public void validateFetchPlan(FetchStrategy fetchStrategy) {
}
@ -138,13 +116,11 @@ public class EntityReturn extends AbstractFetchOwner implements Return, EntityRe
public EntityFetch buildEntityFetch(
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy,
String sqlTableAlias,
LoadPlanBuildingContext loadPlanBuildingContext) {
return LoadPlanBuildingHelper.buildStandardEntityFetch(
this,
attributeDefinition,
fetchStrategy,
sqlTableAlias,
loadPlanBuildingContext
);
}

View File

@ -85,7 +85,6 @@ public interface FetchOwner {
public EntityFetch buildEntityFetch(
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy,
String sqlTableAlias,
LoadPlanBuildingContext loadPlanBuildingContext);
public CompositeFetch buildCompositeFetch(

View File

@ -27,7 +27,6 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.internal.ResultSetProcessingContextImpl;
import org.hibernate.loader.spi.ResultSetProcessingContext;
import org.hibernate.type.Type;
@ -39,12 +38,10 @@ import org.hibernate.type.Type;
*/
public class ScalarReturn extends AbstractPlanNode implements Return {
private final Type type;
private final String[] columnAliases;
public ScalarReturn(SessionFactoryImplementor factory, Type type, String[] columnAliases) {
public ScalarReturn(SessionFactoryImplementor factory, Type type) {
super( factory );
this.type = type;
this.columnAliases = columnAliases;
}
public Type getType() {
@ -63,6 +60,10 @@ public class ScalarReturn extends AbstractPlanNode implements Return {
@Override
public Object read(ResultSet resultSet, ResultSetProcessingContext context) throws SQLException {
return type.nullSafeGet( resultSet, columnAliases, context.getSession(), null );
return type.nullSafeGet(
resultSet,
context.getLoadQueryAliasResolutionContext().resolveScalarReturnAliases( this ),
context.getSession(),
null );
}
}

View File

@ -42,10 +42,6 @@ import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.loader.CollectionAliases;
import org.hibernate.loader.DefaultEntityAliases;
import org.hibernate.loader.EntityAliases;
import org.hibernate.loader.GeneratedCollectionAliases;
import org.hibernate.loader.PropertyPath;
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
import org.hibernate.loader.plan.spi.CollectionFetch;
@ -60,9 +56,7 @@ import org.hibernate.loader.plan.spi.FetchOwner;
import org.hibernate.loader.plan.spi.IdentifierDescription;
import org.hibernate.loader.plan.spi.Return;
import org.hibernate.loader.spi.ResultSetProcessingContext;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Loadable;
import org.hibernate.persister.spi.HydratedCompoundValueHandler;
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
import org.hibernate.persister.walking.spi.AttributeDefinition;
@ -89,9 +83,8 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
private ArrayDeque<FetchOwner> fetchOwnerStack = new ArrayDeque<FetchOwner>();
private ArrayDeque<CollectionReference> collectionReferenceStack = new ArrayDeque<CollectionReference>();
protected AbstractLoadPlanBuilderStrategy(SessionFactoryImplementor sessionFactory, int suffixSeed) {
protected AbstractLoadPlanBuilderStrategy(SessionFactoryImplementor sessionFactory) {
this.sessionFactory = sessionFactory;
this.currentSuffixBase = suffixSeed;
}
public SessionFactoryImplementor sessionFactory() {
@ -416,7 +409,6 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
associationFetch = fetchOwner.buildEntityFetch(
attributeDefinition,
fetchStrategy,
generateEntityFetchSqlTableAlias( attributeDefinition.toEntityDefinition().getEntityPersister().getEntityName() ),
this
);
}
@ -482,60 +474,11 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
// LoadPlanBuildingContext impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private int currentSuffixBase;
private int implicitAliasUniqueness = 0;
private String createImplicitAlias() {
return "ia" + implicitAliasUniqueness++;
}
@Override
public SessionFactoryImplementor getSessionFactory() {
return sessionFactory();
}
protected String generateEntityFetchSqlTableAlias(String entityName) {
return StringHelper.generateAlias( StringHelper.unqualifyEntityName( entityName ), currentDepth() );
}
@Override
public EntityAliases resolveEntityColumnAliases(AssociationAttributeDefinition attributeDefinition) {
return generateEntityColumnAliases( attributeDefinition.toEntityDefinition().getEntityPersister() );
}
protected EntityAliases generateEntityColumnAliases(EntityPersister persister) {
return new DefaultEntityAliases( (Loadable) persister, Integer.toString( currentSuffixBase++ ) + '_' );
}
@Override
public CollectionAliases resolveCollectionColumnAliases(AssociationAttributeDefinition attributeDefinition) {
return generateCollectionColumnAliases( attributeDefinition.toCollectionDefinition().getCollectionPersister() );
}
protected CollectionAliases generateCollectionColumnAliases(CollectionPersister persister) {
return new GeneratedCollectionAliases( persister, Integer.toString( currentSuffixBase++ ) + '_' );
}
@Override
public String resolveRootSourceAlias(EntityDefinition definition) {
return createImplicitAlias();
}
@Override
public String resolveRootSourceAlias(CollectionDefinition definition) {
return createImplicitAlias();
}
@Override
public String resolveFetchSourceAlias(AssociationAttributeDefinition attributeDefinition) {
return createImplicitAlias();
}
@Override
public String resolveFetchSourceAlias(CompositionDefinition compositionDefinition) {
return createImplicitAlias();
}
public static interface FetchStackAware {
public void poppedFromStack();
}
@ -555,21 +498,16 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
this.propertyPath = ( (FetchOwner) entityReference ).getPropertyPath().append( "<id>" );
}
@Override
public String getAlias() {
return entityReference.getAlias();
}
@Override
public String getSqlTableAlias() {
return entityReference.getSqlTableAlias();
}
@Override
public LockMode getLockMode() {
return entityReference.getLockMode();
}
@Override
public EntityReference getEntityReference() {
return this;
}
@Override
public EntityPersister getEntityPersister() {
return entityReference.getEntityPersister();
@ -592,7 +530,6 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
public EntityFetch buildEntityFetch(
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy,
String sqlTableAlias,
LoadPlanBuildingContext loadPlanBuildingContext) {
// we have a key-many-to-one
//
@ -602,7 +539,6 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
this,
attributeDefinition,
fetchStrategy,
sqlTableAlias,
loadPlanBuildingContext
);
fetchToHydratedStateExtractorMap.put( fetch, attributeDefinition.getHydratedCompoundValueExtractor() );
@ -657,11 +593,6 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
return propertyPath;
}
@Override
public EntityAliases getEntityAliases() {
return entityReference.getEntityAliases();
}
@Override
public void injectIdentifierDescription(IdentifierDescription identifierDescription) {
throw new WalkingException(
@ -749,7 +680,7 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
final Object hydratedIdentifierState = entityReference.getEntityPersister().getIdentifierType().hydrate(
resultSet,
entityReference.getEntityAliases().getSuffixedKeyAliases(),
context.getLoadQueryAliasResolutionContext().resolveEntityColumnAliases( entityReference ).getSuffixedKeyAliases(),
context.getSession(),
null
);

View File

@ -24,25 +24,10 @@
package org.hibernate.loader.plan.spi.build;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.CollectionAliases;
import org.hibernate.loader.EntityAliases;
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
import org.hibernate.persister.walking.spi.CollectionDefinition;
import org.hibernate.persister.walking.spi.CompositionDefinition;
import org.hibernate.persister.walking.spi.EntityDefinition;
/**
* @author Steve Ebersole
*/
public interface LoadPlanBuildingContext {
public SessionFactoryImplementor getSessionFactory();
public CollectionAliases resolveCollectionColumnAliases(AssociationAttributeDefinition attributeDefinition);
public EntityAliases resolveEntityColumnAliases(AssociationAttributeDefinition attributeDefinition);
public String resolveRootSourceAlias(EntityDefinition definition);
public String resolveRootSourceAlias(CollectionDefinition definition);
public String resolveFetchSourceAlias(AssociationAttributeDefinition attributeDefinition);
public String resolveFetchSourceAlias(CompositionDefinition compositionDefinition);
}

View File

@ -0,0 +1,66 @@
/*
* 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.spi;
import java.util.Map;
import org.hibernate.Filter;
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.persister.entity.Joinable;
import org.hibernate.sql.JoinType;
import org.hibernate.type.AssociationType;
/**
* @author Gail Badner
*/
public interface JoinableAssociation {
PropertyPath getPropertyPath();
JoinType getJoinType();
Fetch getCurrentFetch();
EntityReference getCurrentEntityReference();
CollectionReference getCurrentCollectionReference();
AssociationType getJoinableType();
Joinable getJoinable();
boolean isCollection();
public String[] getRhsColumns();
boolean hasRestriction();
boolean isManyToManyWith(JoinableAssociation other);
String getWithClause();
Map<String,Filter> getEnabledFilters();
}

View File

@ -0,0 +1,81 @@
/*
* 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.spi;
import org.hibernate.loader.CollectionAliases;
import org.hibernate.loader.EntityAliases;
import org.hibernate.loader.plan.spi.CollectionReturn;
import org.hibernate.loader.plan.spi.CollectionReference;
import org.hibernate.loader.plan.spi.EntityReference;
import org.hibernate.loader.plan.spi.EntityReturn;
import org.hibernate.loader.plan.spi.ScalarReturn;
/**
* @author Gail Badner
*/
public interface LoadQueryAliasResolutionContext {
public String resolveEntityReturnAlias(EntityReturn entityReturn);
public String resolveCollectionReturnAlias(CollectionReturn collectionReturn);
String[] resolveScalarReturnAliases(ScalarReturn scalarReturn);
/**
* Retrieve the SQL table alias.
*
* @return The SQL table alias
*/
String resolveEntitySqlTableAlias(EntityReference entityReference);
EntityAliases resolveEntityColumnAliases(EntityReference entityReference);
String resolveCollectionSqlTableAlias(CollectionReference collectionReference);
/**
* Returns the description of the aliases in the JDBC ResultSet that identify values "belonging" to the
* this collection.
*
* @return The ResultSet alias descriptor for the collection
*/
CollectionAliases resolveCollectionColumnAliases(CollectionReference collectionReference);
/**
* If the elements of this collection are entities, this methods returns the JDBC ResultSet alias descriptions
* for that entity; {@code null} indicates a non-entity collection.
*
* @return The ResultSet alias descriptor for the collection's entity element, or {@code null}
*/
EntityAliases resolveCollectionElementColumnAliases(CollectionReference collectionReference);
String resolveRhsAlias(JoinableAssociation joinableAssociation);
String resolveLhsAlias(JoinableAssociation joinableAssociation);
String[] resolveAliasedLhsColumnNames(JoinableAssociation joinableAssociation);
EntityAliases resolveCurrentEntityAliases(JoinableAssociation joinableAssociation);
CollectionAliases resolveCurrentCollectionAliases(JoinableAssociation joinableAssociation);
}

View File

@ -62,12 +62,14 @@ public interface ResultSetProcessingContext {
public Set<IdentifierResolutionContext> getIdentifierResolutionContexts();
public LoadQueryAliasResolutionContext getLoadQueryAliasResolutionContext();
public void registerHydratedEntity(EntityPersister persister, EntityKey entityKey, Object entityInstance);
public static interface EntityKeyResolutionContext {
public EntityPersister getEntityPersister();
public LockMode getLockMode();
public EntityAliases getEntityAliases();
public EntityReference getEntityReference();
}
public Object resolveEntityKey(EntityKey entityKey, EntityKeyResolutionContext entityKeyContext);

View File

@ -66,6 +66,7 @@ public interface ResultSetProcessor {
SessionImplementor session,
QueryParameters queryParameters,
NamedParameterContext namedParameterContext,
LoadQueryAliasResolutionContext aliasResolutionContext,
boolean returnProxies,
boolean readOnly,
ResultTransformer forcedResultTransformer,

View File

@ -28,6 +28,7 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
@ -45,10 +46,12 @@ import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.jdbc.Work;
import org.hibernate.loader.internal.EntityLoadQueryBuilderImpl;
import org.hibernate.loader.internal.LoadQueryAliasResolutionContextImpl;
import org.hibernate.loader.internal.ResultSetProcessorImpl;
import org.hibernate.loader.plan.internal.SingleRootReturnLoadPlanBuilderStrategy;
import org.hibernate.loader.plan.spi.LoadPlan;
import org.hibernate.loader.plan.spi.build.LoadPlanBuilder;
import org.hibernate.loader.spi.LoadQueryAliasResolutionContext;
import org.hibernate.loader.spi.NamedParameterContext;
import org.hibernate.loader.spi.NoOpLoadPlanAdvisor;
import org.hibernate.persister.entity.EntityPersister;
@ -89,15 +92,20 @@ public class EntityAssociationResultSetProcessorTest extends BaseCoreFunctionalT
{
final SingleRootReturnLoadPlanBuilderStrategy strategy = new SingleRootReturnLoadPlanBuilderStrategy(
sessionFactory(),
LoadQueryInfluencers.NONE,
"abc",
0
LoadQueryInfluencers.NONE
);
final LoadPlan plan = LoadPlanBuilder.buildRootEntityLoadPlan( strategy, entityPersister );
final LoadQueryAliasResolutionContext aliasResolutionContext =
new LoadQueryAliasResolutionContextImpl(
sessionFactory(),
0,
Collections.singletonMap( plan.getReturns().get( 0 ), new String[] { "abc" } )
);
final EntityLoadQueryBuilderImpl queryBuilder = new EntityLoadQueryBuilderImpl(
sessionFactory(),
LoadQueryInfluencers.NONE,
plan
plan,
aliasResolutionContext
);
final String sql = queryBuilder.generateSql( 1 );
@ -125,6 +133,7 @@ public class EntityAssociationResultSetProcessorTest extends BaseCoreFunctionalT
return new int[0];
}
},
aliasResolutionContext,
true,
false,
null,
@ -183,15 +192,20 @@ public class EntityAssociationResultSetProcessorTest extends BaseCoreFunctionalT
{
final SingleRootReturnLoadPlanBuilderStrategy strategy = new SingleRootReturnLoadPlanBuilderStrategy(
sessionFactory(),
LoadQueryInfluencers.NONE,
"abc",
0
LoadQueryInfluencers.NONE
);
final LoadPlan plan = LoadPlanBuilder.buildRootEntityLoadPlan( strategy, entityPersister );
final LoadQueryAliasResolutionContext aliasResolutionContext =
new LoadQueryAliasResolutionContextImpl(
sessionFactory(),
0,
Collections.singletonMap( plan.getReturns().get( 0 ), new String[] { "abc" } )
);
final EntityLoadQueryBuilderImpl queryBuilder = new EntityLoadQueryBuilderImpl(
sessionFactory(),
LoadQueryInfluencers.NONE,
plan
plan,
aliasResolutionContext
);
final String sql = queryBuilder.generateSql( 1 );
@ -219,6 +233,7 @@ public class EntityAssociationResultSetProcessorTest extends BaseCoreFunctionalT
return new int[0];
}
},
aliasResolutionContext,
true,
false,
null,

View File

@ -28,6 +28,7 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@ -45,10 +46,12 @@ import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.jdbc.Work;
import org.hibernate.loader.internal.EntityLoadQueryBuilderImpl;
import org.hibernate.loader.internal.LoadQueryAliasResolutionContextImpl;
import org.hibernate.loader.internal.ResultSetProcessorImpl;
import org.hibernate.loader.plan.internal.SingleRootReturnLoadPlanBuilderStrategy;
import org.hibernate.loader.plan.spi.LoadPlan;
import org.hibernate.loader.plan.spi.build.LoadPlanBuilder;
import org.hibernate.loader.spi.LoadQueryAliasResolutionContext;
import org.hibernate.loader.spi.NamedParameterContext;
import org.hibernate.loader.spi.NoOpLoadPlanAdvisor;
import org.hibernate.persister.entity.EntityPersister;
@ -87,18 +90,29 @@ 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(),
LoadQueryInfluencers.NONE,
"abc",
0
LoadQueryInfluencers.NONE
);
final LoadPlan plan = LoadPlanBuilder.buildRootEntityLoadPlan( strategy, entityPersister );
final LoadQueryAliasResolutionContext aliasResolutionContext =
new LoadQueryAliasResolutionContextImpl(
sessionFactory(),
0,
Collections.singletonMap( plan.getReturns().get( 0 ), new String[] { "abc" } )
);
final EntityLoadQueryBuilderImpl queryBuilder = new EntityLoadQueryBuilderImpl(
sessionFactory(),
LoadQueryInfluencers.NONE,
plan
plan,
aliasResolutionContext
);
final String sql = queryBuilder.generateSql( 1 );
@ -126,6 +140,7 @@ public class EntityWithCollectionResultSetProcessorTest extends BaseCoreFunction
return new int[0];
}
},
aliasResolutionContext,
true,
false,
null,

View File

@ -31,6 +31,7 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.hibernate.Session;
@ -39,10 +40,12 @@ import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.jdbc.Work;
import org.hibernate.loader.internal.EntityLoadQueryBuilderImpl;
import org.hibernate.loader.internal.LoadQueryAliasResolutionContextImpl;
import org.hibernate.loader.internal.ResultSetProcessorImpl;
import org.hibernate.loader.plan.internal.SingleRootReturnLoadPlanBuilderStrategy;
import org.hibernate.loader.plan.spi.LoadPlan;
import org.hibernate.loader.plan.spi.build.LoadPlanBuilder;
import org.hibernate.loader.spi.LoadQueryAliasResolutionContext;
import org.hibernate.loader.spi.NamedParameterContext;
import org.hibernate.loader.spi.NoOpLoadPlanAdvisor;
import org.hibernate.persister.entity.EntityPersister;
@ -79,15 +82,20 @@ public class SimpleResultSetProcessorTest extends BaseCoreFunctionalTestCase {
{
final SingleRootReturnLoadPlanBuilderStrategy strategy = new SingleRootReturnLoadPlanBuilderStrategy(
sessionFactory(),
LoadQueryInfluencers.NONE,
"abc",
0
LoadQueryInfluencers.NONE
);
final LoadPlan plan = LoadPlanBuilder.buildRootEntityLoadPlan( strategy, entityPersister );
final LoadQueryAliasResolutionContext aliasResolutionContext =
new LoadQueryAliasResolutionContextImpl(
sessionFactory(),
0,
Collections.singletonMap( plan.getReturns().get( 0 ), new String[] { "abc" } )
);
final EntityLoadQueryBuilderImpl queryBuilder = new EntityLoadQueryBuilderImpl(
sessionFactory(),
LoadQueryInfluencers.NONE,
plan
plan,
aliasResolutionContext
);
final String sql = queryBuilder.generateSql( 1 );
@ -115,6 +123,7 @@ public class SimpleResultSetProcessorTest extends BaseCoreFunctionalTestCase {
return new int[0];
}
},
aliasResolutionContext,
true,
false,
null,

View File

@ -33,11 +33,9 @@ import java.util.List;
import org.hibernate.engine.spi.CascadingActions;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.loader.internal.EntityLoadQueryBuilderImpl;
import org.hibernate.loader.plan.internal.CascadeLoadPlanBuilderStrategy;
import org.hibernate.loader.plan.internal.SingleRootReturnLoadPlanBuilderStrategy;
import org.hibernate.loader.plan.spi.build.LoadPlanBuilder;
import org.hibernate.loader.spi.LoadQueryBuilder;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
@ -64,25 +62,19 @@ public class LoadPlanBuilderTest extends BaseCoreFunctionalTestCase {
EntityPersister ep = (EntityPersister) sessionFactory().getClassMetadata(Message.class);
SingleRootReturnLoadPlanBuilderStrategy strategy = new SingleRootReturnLoadPlanBuilderStrategy(
sessionFactory(),
LoadQueryInfluencers.NONE,
"abc",
0
LoadQueryInfluencers.NONE
);
LoadPlan plan = LoadPlanBuilder.buildRootEntityLoadPlan( strategy, ep );
assertFalse( plan.hasAnyScalarReturns() );
assertEquals( 1, plan.getReturns().size() );
Return rtn = plan.getReturns().get( 0 );
EntityReturn entityReturn = ExtraAssertions.assertTyping( EntityReturn.class, rtn );
assertEquals( "abc", entityReturn.getAlias() );
assertNotNull( entityReturn.getFetches() );
assertEquals( 1, entityReturn.getFetches().length );
Fetch fetch = entityReturn.getFetches()[0];
EntityFetch entityFetch = ExtraAssertions.assertTyping( EntityFetch.class, fetch );
assertNotNull( entityFetch.getFetches() );
assertEquals( 0, entityFetch.getFetches().length );
LoadQueryBuilder loadQueryBuilder = new EntityLoadQueryBuilderImpl( sessionFactory(), LoadQueryInfluencers.NONE, plan );
String sql = loadQueryBuilder.generateSql( 1 );
}
@Test
@ -91,16 +83,13 @@ public class LoadPlanBuilderTest extends BaseCoreFunctionalTestCase {
CascadeLoadPlanBuilderStrategy strategy = new CascadeLoadPlanBuilderStrategy(
CascadingActions.MERGE,
sessionFactory(),
LoadQueryInfluencers.NONE,
"abc",
0
LoadQueryInfluencers.NONE
);
LoadPlan plan = LoadPlanBuilder.buildRootEntityLoadPlan( strategy, ep );
assertFalse( plan.hasAnyScalarReturns() );
assertEquals( 1, plan.getReturns().size() );
Return rtn = plan.getReturns().get( 0 );
EntityReturn entityReturn = ExtraAssertions.assertTyping( EntityReturn.class, rtn );
assertEquals( "abc", entityReturn.getAlias() );
assertNotNull( entityReturn.getFetches() );
assertEquals( 1, entityReturn.getFetches().length );
Fetch fetch = entityReturn.getFetches()[0];
@ -114,16 +103,13 @@ public class LoadPlanBuilderTest extends BaseCoreFunctionalTestCase {
CollectionPersister cp = sessionFactory().getCollectionPersister( Poster.class.getName() + ".messages" );
SingleRootReturnLoadPlanBuilderStrategy strategy = new SingleRootReturnLoadPlanBuilderStrategy(
sessionFactory(),
LoadQueryInfluencers.NONE,
"abc",
0
LoadQueryInfluencers.NONE
);
LoadPlan plan = LoadPlanBuilder.buildRootCollectionLoadPlan( strategy, cp );
assertFalse( plan.hasAnyScalarReturns() );
assertEquals( 1, plan.getReturns().size() );
Return rtn = plan.getReturns().get( 0 );
CollectionReturn collectionReturn = ExtraAssertions.assertTyping( CollectionReturn.class, rtn );
assertEquals( "abc", collectionReturn.getAlias() );
assertNotNull( collectionReturn.getElementGraph().getFetches() );
assertEquals( 1, collectionReturn.getElementGraph().getFetches().length ); // the collection elements are fetched