HHH-7841 - Redesign Loader
This commit is contained in:
parent
0416d3f24a
commit
f3298620ee
|
@ -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() {
|
||||
|
|
|
@ -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 )
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
);
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
|
|
|
@ -85,7 +85,6 @@ public interface FetchOwner {
|
|||
public EntityFetch buildEntityFetch(
|
||||
AssociationAttributeDefinition attributeDefinition,
|
||||
FetchStrategy fetchStrategy,
|
||||
String sqlTableAlias,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext);
|
||||
|
||||
public CompositeFetch buildCompositeFetch(
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -66,6 +66,7 @@ public interface ResultSetProcessor {
|
|||
SessionImplementor session,
|
||||
QueryParameters queryParameters,
|
||||
NamedParameterContext namedParameterContext,
|
||||
LoadQueryAliasResolutionContext aliasResolutionContext,
|
||||
boolean returnProxies,
|
||||
boolean readOnly,
|
||||
ResultTransformer forcedResultTransformer,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue