HHH-8629 : Integrate LoadPlans into collection initializers

This commit is contained in:
Gail Badner 2013-11-08 18:39:16 -08:00
parent fdf211fdd1
commit b7f17e9412
23 changed files with 381 additions and 344 deletions

View File

@ -24,6 +24,8 @@
package org.hibernate.loader.plan2.build.internal.returns;
import org.hibernate.loader.PropertyPath;
import org.hibernate.loader.plan2.build.internal.spaces.CompositePropertyMapping;
import org.hibernate.loader.plan2.build.internal.spaces.QuerySpaceHelper;
import org.hibernate.loader.plan2.build.spi.ExpandingCollectionQuerySpace;
import org.hibernate.loader.plan2.build.spi.ExpandingCompositeQuerySpace;
import org.hibernate.loader.plan2.build.spi.ExpandingEntityQuerySpace;
@ -31,7 +33,9 @@ import org.hibernate.loader.plan2.spi.CollectionFetchableElement;
import org.hibernate.loader.plan2.spi.CollectionFetchableIndex;
import org.hibernate.loader.plan2.spi.CollectionReference;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.collection.CollectionPropertyNames;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.PropertyMapping;
import org.hibernate.type.CompositeType;
import org.hibernate.type.EntityType;
import org.hibernate.type.Type;
@ -48,15 +52,18 @@ public abstract class AbstractCollectionReference implements CollectionReference
protected AbstractCollectionReference(
ExpandingCollectionQuerySpace collectionQuerySpace,
PropertyPath propertyPath) {
PropertyPath propertyPath,
boolean shouldIncludeJoins) {
this.collectionQuerySpace = collectionQuerySpace;
this.propertyPath = propertyPath;
this.index = buildIndexGraph( collectionQuerySpace );
this.element = buildElementGraph( collectionQuerySpace );
this.index = buildIndexGraph( collectionQuerySpace, shouldIncludeJoins );
this.element = buildElementGraph( collectionQuerySpace, shouldIncludeJoins );
}
private CollectionFetchableIndex buildIndexGraph(ExpandingCollectionQuerySpace collectionQuerySpace) {
private CollectionFetchableIndex buildIndexGraph(
ExpandingCollectionQuerySpace collectionQuerySpace,
boolean shouldIncludeJoins) {
final CollectionPersister persister = collectionQuerySpace.getCollectionPersister();
if ( persister.hasIndex() ) {
final Type type = persister.getIndexType();
@ -66,15 +73,31 @@ public abstract class AbstractCollectionReference implements CollectionReference
( (EntityType) type ).getAssociatedEntityName()
);
final ExpandingEntityQuerySpace entityQuerySpace = collectionQuerySpace.addIndexEntityQuerySpace(
indexPersister
final ExpandingEntityQuerySpace entityQuerySpace = QuerySpaceHelper.INSTANCE.makeEntityQuerySpace(
collectionQuerySpace,
indexPersister,
CollectionPropertyNames.COLLECTION_INDICES,
(EntityType) persister.getIndexType(),
collectionQuerySpace.getExpandingQuerySpaces().generateImplicitUid(),
collectionQuerySpace.canJoinsBeRequired(),
shouldIncludeJoins
);
return new CollectionFetchableIndexEntityGraph( this, entityQuerySpace );
}
}
else if ( type.isComponentType() ) {
final ExpandingCompositeQuerySpace compositeQuerySpace = collectionQuerySpace.addIndexCompositeQuerySpace(
(CompositeType) type
final ExpandingCompositeQuerySpace compositeQuerySpace = QuerySpaceHelper.INSTANCE.makeCompositeQuerySpace(
collectionQuerySpace,
new CompositePropertyMapping(
(CompositeType) persister.getIndexType(),
(PropertyMapping) persister,
""
),
CollectionPropertyNames.COLLECTION_INDICES,
(CompositeType) persister.getIndexType(),
collectionQuerySpace.getExpandingQuerySpaces().generateImplicitUid(),
collectionQuerySpace.canJoinsBeRequired(),
shouldIncludeJoins
);
return new CollectionFetchableIndexCompositeGraph( this, compositeQuerySpace );
}
@ -84,7 +107,8 @@ public abstract class AbstractCollectionReference implements CollectionReference
}
private CollectionFetchableElement buildElementGraph(
ExpandingCollectionQuerySpace collectionQuerySpace) {
ExpandingCollectionQuerySpace collectionQuerySpace,
boolean shouldIncludeJoins) {
final CollectionPersister persister = collectionQuerySpace.getCollectionPersister();
final Type type = persister.getElementType();
if ( type.isAssociationType() ) {
@ -92,16 +116,31 @@ public abstract class AbstractCollectionReference implements CollectionReference
final EntityPersister elementPersister = persister.getFactory().getEntityPersister(
( (EntityType) type ).getAssociatedEntityName()
);
final ExpandingEntityQuerySpace entityQuerySpace = collectionQuerySpace.addElementEntityQuerySpace(
elementPersister
final ExpandingEntityQuerySpace entityQuerySpace = QuerySpaceHelper.INSTANCE.makeEntityQuerySpace(
collectionQuerySpace,
elementPersister,
CollectionPropertyNames.COLLECTION_ELEMENTS,
(EntityType) persister.getElementType(),
collectionQuerySpace.getExpandingQuerySpaces().generateImplicitUid(),
collectionQuerySpace.canJoinsBeRequired(),
shouldIncludeJoins
);
return new CollectionFetchableElementEntityGraph( this, entityQuerySpace );
}
}
else if ( type.isComponentType() ) {
final ExpandingCompositeQuerySpace compositeQuerySpace = collectionQuerySpace.addElementCompositeQuerySpace(
(CompositeType) type
final ExpandingCompositeQuerySpace compositeQuerySpace = QuerySpaceHelper.INSTANCE.makeCompositeQuerySpace(
collectionQuerySpace,
new CompositePropertyMapping(
(CompositeType) persister.getElementType(),
(PropertyMapping) persister,
""
),
CollectionPropertyNames.COLLECTION_ELEMENTS,
(CompositeType) persister.getElementType(),
collectionQuerySpace.getExpandingQuerySpaces().generateImplicitUid(),
collectionQuerySpace.canJoinsBeRequired(),
shouldIncludeJoins
);
return new CollectionFetchableElementCompositeGraph( this, compositeQuerySpace );
}

View File

@ -30,24 +30,23 @@ import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.FetchTiming;
import org.hibernate.loader.PropertyPath;
import org.hibernate.loader.plan2.build.internal.spaces.QuerySpaceHelper;
import org.hibernate.loader.plan2.build.spi.ExpandingCollectionQuerySpace;
import org.hibernate.loader.plan2.build.spi.ExpandingCompositeQuerySpace;
import org.hibernate.loader.plan2.build.spi.ExpandingEntityQuerySpace;
import org.hibernate.loader.plan2.build.spi.ExpandingFetchSource;
import org.hibernate.loader.plan2.build.spi.ExpandingQuerySpace;
import org.hibernate.loader.plan2.build.spi.ExpandingQuerySpaces;
import org.hibernate.loader.plan2.build.spi.ExpandingSourceQuerySpace;
import org.hibernate.loader.plan2.spi.BidirectionalEntityReference;
import org.hibernate.loader.plan2.spi.CollectionFetch;
import org.hibernate.loader.plan2.spi.CompositeFetch;
import org.hibernate.loader.plan2.spi.EntityFetch;
import org.hibernate.loader.plan2.spi.EntityReference;
import org.hibernate.loader.plan2.spi.Fetch;
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.CompositionDefinition;
import org.hibernate.persister.walking.spi.WalkingException;
import org.hibernate.type.CollectionType;
import org.hibernate.type.EntityType;
/**
@ -65,12 +64,12 @@ public abstract class AbstractExpandingFetchSource implements ExpandingFetchSour
private static final BidirectionalEntityReference[] NO_BIDIRECTIONAL_ENTITY_REFERENCES =
new BidirectionalEntityReference[0];
private final ExpandingSourceQuerySpace querySpace;
private final ExpandingQuerySpace querySpace;
private final PropertyPath propertyPath;
private List<Fetch> fetches;
private List<BidirectionalEntityReference> bidirectionalEntityReferences;
public AbstractExpandingFetchSource(ExpandingSourceQuerySpace querySpace, PropertyPath propertyPath) {
public AbstractExpandingFetchSource(ExpandingQuerySpace querySpace, PropertyPath propertyPath) {
this.querySpace = querySpace;
this.propertyPath = propertyPath;
}
@ -80,7 +79,7 @@ public abstract class AbstractExpandingFetchSource implements ExpandingFetchSour
return querySpace.getUid();
}
protected final ExpandingSourceQuerySpace expandingQuerySpace() {
protected final ExpandingQuerySpace expandingQuerySpace() {
return querySpace;
}
@ -121,25 +120,12 @@ public abstract class AbstractExpandingFetchSource implements ExpandingFetchSour
public EntityFetch buildEntityFetch(
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy) {
final EntityType fetchedType = (EntityType) attributeDefinition.getType();
final EntityPersister fetchedPersister = attributeDefinition.toEntityDefinition().getEntityPersister();
if ( fetchedPersister == null ) {
throw new WalkingException(
String.format(
"Unable to locate EntityPersister [%s] for fetch [%s]",
fetchedType.getAssociatedEntityName(),
attributeDefinition.getName()
)
);
}
final ExpandingEntityQuerySpace entityQuerySpace = querySpace.addEntityQuerySpace(
final ExpandingEntityQuerySpace entityQuerySpace = QuerySpaceHelper.INSTANCE.makeEntityQuerySpace(
expandingQuerySpace(),
attributeDefinition,
fetchedPersister,
getQuerySpaces().generateImplicitUid(),
attributeDefinition.isNullable(),
shouldIncludeJoin( fetchStrategy )
fetchStrategy
);
final EntityFetch fetch = new EntityFetchImpl( this, attributeDefinition, fetchStrategy, entityQuerySpace );
addFetch( fetch );
@ -181,12 +167,13 @@ public abstract class AbstractExpandingFetchSource implements ExpandingFetchSour
@Override
public CompositeFetch buildCompositeFetch(
CompositionDefinition attributeDefinition) {
final ExpandingSourceQuerySpace leftHandSide = expandingQuerySpace();
final ExpandingCompositeQuerySpace compositeQuerySpace = leftHandSide.addCompositeQuerySpace(
final ExpandingCompositeQuerySpace compositeQuerySpace = QuerySpaceHelper.INSTANCE.makeCompositeQuerySpace(
expandingQuerySpace(),
attributeDefinition,
getQuerySpaces().generateImplicitUid(),
shouldIncludeJoin( AbstractCompositeFetch.FETCH_STRATEGY )
true
);
final CompositeFetch fetch = createCompositeFetch( attributeDefinition, compositeQuerySpace );
addFetch( fetch );
return fetch;
@ -197,27 +184,13 @@ public abstract class AbstractExpandingFetchSource implements ExpandingFetchSour
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy) {
// general question here wrt Joins and collection fetches... do we create multiple Joins for many-to-many,
// for example, or do we allow the Collection QuerySpace to handle that?
final CollectionType fetchedType = (CollectionType) attributeDefinition.getType();
final CollectionPersister fetchedPersister = attributeDefinition.toCollectionDefinition().getCollectionPersister();
if ( fetchedPersister == null ) {
throw new WalkingException(
String.format(
"Unable to locate CollectionPersister [%s] for fetch [%s]",
fetchedType.getRole(),
attributeDefinition.getName()
)
);
}
final ExpandingCollectionQuerySpace collectionQuerySpace = querySpace.addCollectionQuerySpace(
final ExpandingCollectionQuerySpace collectionQuerySpace = QuerySpaceHelper.INSTANCE.makeCollectionQuerySpace(
querySpace,
attributeDefinition,
fetchedPersister,
getQuerySpaces().generateImplicitUid(),
shouldIncludeJoin( fetchStrategy )
fetchStrategy
);
final CollectionFetch fetch = new CollectionFetchImpl(
this,
attributeDefinition,
@ -227,8 +200,4 @@ public abstract class AbstractExpandingFetchSource implements ExpandingFetchSour
addFetch( fetch );
return fetch;
}
private boolean shouldIncludeJoin(FetchStrategy fetchStrategy) {
return fetchStrategy.getTiming() == FetchTiming.IMMEDIATE && fetchStrategy.getStyle() == FetchStyle.JOIN;
}
}

View File

@ -24,6 +24,7 @@
package org.hibernate.loader.plan2.build.internal.returns;
import org.hibernate.engine.FetchStrategy;
import org.hibernate.loader.plan2.build.internal.spaces.QuerySpaceHelper;
import org.hibernate.loader.plan2.build.spi.ExpandingCollectionQuerySpace;
import org.hibernate.loader.plan2.build.spi.ExpandingFetchSource;
import org.hibernate.loader.plan2.spi.CollectionFetch;
@ -47,7 +48,9 @@ public class CollectionFetchImpl extends AbstractCollectionReference implements
ExpandingCollectionQuerySpace collectionQuerySpace) {
super(
collectionQuerySpace,
fetchSource.getPropertyPath().append( fetchedAttribute.getName() )
fetchSource.getPropertyPath().append( fetchedAttribute.getName() ),
QuerySpaceHelper.INSTANCE.shouldIncludeJoin( fetchStrategy )
);
this.fetchSource = fetchSource;

View File

@ -45,7 +45,7 @@ public class CollectionFetchableElementCompositeGraph
CollectionReference collectionReference,
ExpandingCompositeQuerySpace compositeQuerySpace) {
super(
(CompositeType) compositeQuerySpace.getPropertyMapping().getType(),
(CompositeType) collectionReference.getCollectionPersister().getElementType(),
compositeQuerySpace,
false,
// these property paths are just informational...

View File

@ -28,7 +28,6 @@ import org.hibernate.loader.plan2.spi.CollectionFetchableIndex;
import org.hibernate.loader.plan2.spi.CollectionReference;
import org.hibernate.loader.plan2.spi.CompositeFetch;
import org.hibernate.loader.plan2.spi.FetchSource;
import org.hibernate.loader.plan2.spi.Join;
import org.hibernate.type.CompositeType;
import org.hibernate.type.Type;
@ -48,7 +47,7 @@ public class CollectionFetchableIndexCompositeGraph
CollectionReference collectionReference,
ExpandingCompositeQuerySpace compositeQuerySpace) {
super(
extractIndexType( compositeQuerySpace ),
(CompositeType) collectionReference.getCollectionPersister().getIndexType(),
compositeQuerySpace,
false,
collectionReference.getPropertyPath().append( "<index>" )
@ -56,15 +55,6 @@ public class CollectionFetchableIndexCompositeGraph
this.collectionReference = collectionReference;
}
private static CompositeType extractIndexType(ExpandingCompositeQuerySpace compositeQuerySpace) {
final Type type = compositeQuerySpace.getPropertyMapping().getType();
if ( CompositeType.class.isInstance( type ) ) {
return (CompositeType) type;
}
throw new IllegalArgumentException( "Could note extract collection composite-index" );
}
@Override
public CollectionReference getCollectionReference() {
return collectionReference;

View File

@ -39,7 +39,8 @@ public class CollectionReturnImpl extends AbstractCollectionReference implements
querySpaces.generateImplicitUid(),
collectionDefinition.getCollectionPersister()
),
new PropertyPath( "[" + collectionDefinition.getCollectionPersister().getRole() + "]" )
new PropertyPath( "[" + collectionDefinition.getCollectionPersister().getRole() + "]" ),
true
);
}
}

View File

@ -24,124 +24,26 @@
package org.hibernate.loader.plan2.build.internal.spaces;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.plan2.build.spi.ExpandingCollectionQuerySpace;
import org.hibernate.loader.plan2.build.spi.ExpandingCompositeQuerySpace;
import org.hibernate.loader.plan2.build.spi.ExpandingEntityQuerySpace;
import org.hibernate.loader.plan2.build.spi.ExpandingQuerySpace;
import org.hibernate.loader.plan2.build.spi.ExpandingQuerySpaces;
import org.hibernate.loader.plan2.build.spi.ExpandingSourceQuerySpace;
import org.hibernate.loader.plan2.spi.JoinDefinedByMetadata;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Queryable;
import org.hibernate.persister.walking.spi.AttributeDefinition;
import org.hibernate.persister.walking.spi.CompositionDefinition;
import org.hibernate.type.CollectionType;
import org.hibernate.type.EntityType;
import org.hibernate.loader.plan2.spi.Join;
/**
* @author Gail Badner
*/
public abstract class AbstractExpandingSourceQuerySpace extends AbstractQuerySpace implements ExpandingSourceQuerySpace {
public abstract class AbstractExpandingSourceQuerySpace extends AbstractQuerySpace implements ExpandingQuerySpace {
public AbstractExpandingSourceQuerySpace(
String uid,
Disposition disposition,
ExpandingQuerySpaces querySpaces,
boolean canJoinsBeRequired,
SessionFactoryImplementor sessionFactory) {
super( uid, disposition, querySpaces, canJoinsBeRequired, sessionFactory );
boolean canJoinsBeRequired) {
super( uid, disposition, querySpaces, canJoinsBeRequired );
}
@Override
public ExpandingCompositeQuerySpace addCompositeQuerySpace(
CompositionDefinition compositionDefinition,
String querySpaceUid,
boolean shouldIncludeJoin) {
final boolean required = canJoinsBeRequired() && !compositionDefinition.isNullable();
final ExpandingCompositeQuerySpace rhs = getExpandingQuerySpaces().makeCompositeQuerySpace(
querySpaceUid,
new CompositePropertyMapping(
compositionDefinition.getType(),
getPropertyMapping(),
compositionDefinition.getName()
),
required
);
if ( shouldIncludeJoin ) {
final JoinDefinedByMetadata join = JoinHelper.INSTANCE.createCompositeJoin(
this,
compositionDefinition.getName(),
rhs,
required,
compositionDefinition.getType()
);
internalGetJoins().add( join );
}
return rhs;
}
@Override
public ExpandingEntityQuerySpace addEntityQuerySpace(
AttributeDefinition attribute,
EntityPersister persister,
String querySpaceUid,
boolean optional,
boolean shouldIncludeJoin) {
// TODO: Queryable.isMultiTable() may be more broad than it needs to be...
final boolean isMultiTable = Queryable.class.cast( persister ).isMultiTable();
final boolean required = canJoinsBeRequired() && !isMultiTable && !optional;
final ExpandingEntityQuerySpace rhs = getExpandingQuerySpaces().makeEntityQuerySpace(
querySpaceUid,
persister,
required
);
if ( shouldIncludeJoin ) {
final JoinDefinedByMetadata join = JoinHelper.INSTANCE.createEntityJoin(
this,
attribute.getName(),
rhs,
required,
(EntityType) attribute.getType(),
sessionFactory()
);
internalGetJoins().add( join );
}
return rhs;
}
@Override
public ExpandingCollectionQuerySpace addCollectionQuerySpace(
AttributeDefinition attributeDefinition,
CollectionPersister collectionPersister,
String querySpaceUid,
boolean shouldIncludeJoin) {
final boolean required = canJoinsBeRequired() && !attributeDefinition.isNullable();
final ExpandingCollectionQuerySpace rhs = getExpandingQuerySpaces().makeCollectionQuerySpace(
querySpaceUid,
collectionPersister,
required
);
if ( shouldIncludeJoin ) {
final JoinDefinedByMetadata join = JoinHelper.INSTANCE.createCollectionJoin(
this,
attributeDefinition.getName(),
rhs,
required,
(CollectionType) attributeDefinition.getType(),
sessionFactory()
);
internalGetJoins().add( join );
}
return rhs;
public void addJoin(Join join) {
internalGetJoins().add( join );
}
@Override

View File

@ -51,9 +51,8 @@ public abstract class AbstractQuerySpace extends AbstractPlanNode implements Que
String uid,
Disposition disposition,
ExpandingQuerySpaces querySpaces,
boolean canJoinsBeRequired,
SessionFactoryImplementor sessionFactory) {
super( sessionFactory );
boolean canJoinsBeRequired) {
super( querySpaces.getSessionFactory() );
this.uid = uid;
this.disposition = disposition;
this.querySpaces = querySpaces;

View File

@ -23,37 +23,27 @@
*/
package org.hibernate.loader.plan2.build.internal.spaces;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.plan2.build.spi.ExpandingCollectionQuerySpace;
import org.hibernate.loader.plan2.build.spi.ExpandingCompositeQuerySpace;
import org.hibernate.loader.plan2.build.spi.ExpandingEntityQuerySpace;
import org.hibernate.loader.plan2.build.spi.ExpandingQuerySpaces;
import org.hibernate.loader.plan2.spi.JoinDefinedByMetadata;
import org.hibernate.loader.plan2.spi.Join;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.collection.CollectionPropertyMapping;
import org.hibernate.persister.collection.CollectionPropertyNames;
import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.PropertyMapping;
import org.hibernate.type.CompositeType;
import org.hibernate.type.EntityType;
/**
* @author Steve Ebersole
*/
public class CollectionQuerySpaceImpl extends AbstractQuerySpace implements ExpandingCollectionQuerySpace {
private final CollectionPersister persister;
private final CollectionPropertyMapping propertyMapping;
public CollectionQuerySpaceImpl(
CollectionPersister persister,
String uid,
ExpandingQuerySpaces querySpaces,
boolean canJoinsBeRequired,
SessionFactoryImplementor sessionFactory) {
super( uid, Disposition.COLLECTION, querySpaces, canJoinsBeRequired, sessionFactory );
boolean canJoinsBeRequired) {
super( uid, Disposition.COLLECTION, querySpaces, canJoinsBeRequired );
this.persister = persister;
this.propertyMapping = new CollectionPropertyMapping( (QueryableCollection) persister );
}
@Override
@ -63,108 +53,37 @@ public class CollectionQuerySpaceImpl extends AbstractQuerySpace implements Expa
@Override
public PropertyMapping getPropertyMapping() {
return propertyMapping;
return (PropertyMapping) persister;
}
public String[] toAliasedColumns(String alias, String propertyName) {
final QueryableCollection queryableCollection = (QueryableCollection) persister;
if ( propertyName.equals( CollectionPropertyNames.COLLECTION_ELEMENTS ) ) {
return queryableCollection.getElementColumnNames( alias );
}
else if ( propertyName.equals( CollectionPropertyNames.COLLECTION_INDICES ) ) {
return queryableCollection.getIndexColumnNames( alias );
}
else {
throw new IllegalArgumentException(
String.format(
"Collection propertyName must be either %s or %s; instead it was %s.",
CollectionPropertyNames.COLLECTION_ELEMENTS,
CollectionPropertyNames.COLLECTION_INDICES,
propertyName
)
);
}
}
@Override
public ExpandingEntityQuerySpace addIndexEntityQuerySpace(
final EntityPersister indexPersister) {
final boolean required = canJoinsBeRequired();
final String entityQuerySpaceUid = getExpandingQuerySpaces().generateImplicitUid();
final ExpandingEntityQuerySpace entityQuerySpace = getExpandingQuerySpaces().makeEntityQuerySpace(
entityQuerySpaceUid,
indexPersister,
required
);
final JoinDefinedByMetadata join = JoinHelper.INSTANCE.createEntityJoin(
this,
// collection persister maps its index (through its PropertyMapping contract) as non-prefixed
CollectionPropertyNames.COLLECTION_INDICES,
entityQuerySpace,
required,
(EntityType) persister.getIndexType(),
sessionFactory()
);
public void addJoin(Join join) {
internalGetJoins().add( join );
return entityQuerySpace;
}
@Override
public ExpandingCompositeQuerySpace addIndexCompositeQuerySpace(
CompositeType compositeType) {
final String compositeQuerySpaceUid = getExpandingQuerySpaces().generateImplicitUid();
final ExpandingCompositeQuerySpace compositeQuerySpace = getExpandingQuerySpaces().makeCompositeQuerySpace(
compositeQuerySpaceUid,
new CompositePropertyMapping(
compositeType,
(PropertyMapping) getCollectionPersister(),
"index"
),
canJoinsBeRequired()
);
final JoinDefinedByMetadata join = JoinHelper.INSTANCE.createCompositeJoin(
this,
CollectionPropertyNames.COLLECTION_INDICES,
compositeQuerySpace,
canJoinsBeRequired(),
compositeType
);
internalGetJoins().add( join );
return compositeQuerySpace;
public ExpandingQuerySpaces getExpandingQuerySpaces() {
return super.getExpandingQuerySpaces();
}
@Override
public ExpandingEntityQuerySpace addElementEntityQuerySpace(
final EntityPersister elementPersister) {
final String entityQuerySpaceUid = getExpandingQuerySpaces().generateImplicitUid();
final ExpandingEntityQuerySpace entityQuerySpace = getExpandingQuerySpaces().makeEntityQuerySpace(
entityQuerySpaceUid,
elementPersister,
canJoinsBeRequired()
);
final JoinDefinedByMetadata join = JoinHelper.INSTANCE.createEntityJoin(
this,
// collection persister maps its elements (through its PropertyMapping contract) as non-prefixed
CollectionPropertyNames.COLLECTION_ELEMENTS,
entityQuerySpace,
canJoinsBeRequired(),
(EntityType) persister.getElementType(),
sessionFactory()
);
internalGetJoins().add( join );
return entityQuerySpace;
}
@Override
public ExpandingCompositeQuerySpace addElementCompositeQuerySpace(
CompositeType compositeType) {
final String compositeQuerySpaceUid = getExpandingQuerySpaces().generateImplicitUid();
final ExpandingCompositeQuerySpace compositeQuerySpace = getExpandingQuerySpaces().makeCompositeQuerySpace(
compositeQuerySpaceUid,
new CompositePropertyMapping(
compositeType,
(PropertyMapping) getCollectionPersister(),
""
),
canJoinsBeRequired()
);
final JoinDefinedByMetadata join = JoinHelper.INSTANCE.createCompositeJoin(
this,
// collection persister maps its elements (through its PropertyMapping contract) as non-prefixed
CollectionPropertyNames.COLLECTION_ELEMENTS,
compositeQuerySpace,
canJoinsBeRequired(),
compositeType
);
internalGetJoins().add( join );
return compositeQuerySpace;
}
}

View File

@ -23,7 +23,6 @@
*/
package org.hibernate.loader.plan2.build.internal.spaces;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.plan2.build.spi.ExpandingCompositeQuerySpace;
import org.hibernate.loader.plan2.build.spi.ExpandingQuerySpaces;
import org.hibernate.persister.entity.PropertyMapping;
@ -38,9 +37,8 @@ public class CompositeQuerySpaceImpl extends AbstractExpandingSourceQuerySpace i
CompositePropertyMapping compositeSubPropertyMapping,
String uid,
ExpandingQuerySpaces querySpaces,
boolean canJoinsBeRequired,
SessionFactoryImplementor sessionFactory) {
super( uid, Disposition.COMPOSITE, querySpaces, canJoinsBeRequired, sessionFactory );
boolean canJoinsBeRequired) {
super( uid, Disposition.COMPOSITE, querySpaces, canJoinsBeRequired );
this.compositeSubPropertyMapping = compositeSubPropertyMapping;
}
@ -48,4 +46,9 @@ public class CompositeQuerySpaceImpl extends AbstractExpandingSourceQuerySpace i
public PropertyMapping getPropertyMapping() {
return compositeSubPropertyMapping;
}
@Override
public String[] toAliasedColumns(String alias, String propertyName) {
return compositeSubPropertyMapping.toColumns( alias,propertyName );
}
}

View File

@ -42,9 +42,8 @@ public class EntityQuerySpaceImpl extends AbstractExpandingSourceQuerySpace impl
EntityPersister persister,
String uid,
ExpandingQuerySpaces querySpaces,
boolean canJoinsBeRequired,
SessionFactoryImplementor sessionFactory) {
super( uid, Disposition.ENTITY, querySpaces, canJoinsBeRequired, sessionFactory );
boolean canJoinsBeRequired) {
super( uid, Disposition.ENTITY, querySpaces, canJoinsBeRequired );
this.persister = persister;
}
@ -60,6 +59,11 @@ public class EntityQuerySpaceImpl extends AbstractExpandingSourceQuerySpace impl
return (PropertyMapping) persister;
}
@Override
public String[] toAliasedColumns(String alias, String propertyName) {
return getPropertyMapping().toColumns( alias, propertyName );
}
@Override
public EntityPersister getEntityPersister() {
return persister;

View File

@ -76,7 +76,7 @@ public class JoinImpl implements JoinDefinedByMetadata {
@Override
public String[] resolveAliasedLeftHandSideJoinConditionColumns(String leftHandSideTableAlias) {
return getLeftHandSide().getPropertyMapping().toColumns( leftHandSideTableAlias, getJoinedPropertyName() );
return getLeftHandSide().toAliasedColumns( leftHandSideTableAlias, getJoinedPropertyName() );
}
@Override

View File

@ -0,0 +1,214 @@
/*
* 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.plan2.build.internal.spaces;
import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.FetchTiming;
import org.hibernate.loader.plan2.build.spi.ExpandingCollectionQuerySpace;
import org.hibernate.loader.plan2.build.spi.ExpandingCompositeQuerySpace;
import org.hibernate.loader.plan2.build.spi.ExpandingEntityQuerySpace;
import org.hibernate.loader.plan2.build.spi.ExpandingQuerySpace;
import org.hibernate.loader.plan2.spi.JoinDefinedByMetadata;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Queryable;
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
import org.hibernate.persister.walking.spi.CompositionDefinition;
import org.hibernate.persister.walking.spi.WalkingException;
import org.hibernate.type.CollectionType;
import org.hibernate.type.CompositeType;
import org.hibernate.type.EntityType;
/**
* @author Gail Badner
*/
public class QuerySpaceHelper {
/**
* Singleton access
*/
public static final QuerySpaceHelper INSTANCE = new QuerySpaceHelper();
private QuerySpaceHelper() {
}
public ExpandingEntityQuerySpace makeEntityQuerySpace(
ExpandingQuerySpace lhsQuerySpace,
AssociationAttributeDefinition attribute,
String querySpaceUid,
FetchStrategy fetchStrategy) {
final EntityType fetchedType = (EntityType) attribute.getType();
final EntityPersister fetchedPersister = attribute.toEntityDefinition().getEntityPersister();
if ( fetchedPersister == null ) {
throw new WalkingException(
String.format(
"Unable to locate EntityPersister [%s] for fetch [%s]",
fetchedType.getAssociatedEntityName(),
attribute.getName()
)
);
}
// TODO: Queryable.isMultiTable() may be more broad than it needs to be...
final boolean isMultiTable = Queryable.class.cast( fetchedPersister ).isMultiTable();
final boolean required = lhsQuerySpace.canJoinsBeRequired() && !isMultiTable && !attribute.isNullable();
return makeEntityQuerySpace(
lhsQuerySpace,
fetchedPersister,
attribute.getName(),
(EntityType) attribute.getType(),
querySpaceUid,
required,
shouldIncludeJoin( fetchStrategy )
);
}
public ExpandingEntityQuerySpace makeEntityQuerySpace(
ExpandingQuerySpace lhsQuerySpace,
EntityPersister fetchedPersister,
String attributeName,
EntityType attributeType,
String querySpaceUid,
boolean required,
boolean shouldIncludeJoin) {
final ExpandingEntityQuerySpace rhs = lhsQuerySpace.getExpandingQuerySpaces().makeEntityQuerySpace(
querySpaceUid,
fetchedPersister,
required
);
if ( shouldIncludeJoin ) {
final JoinDefinedByMetadata join = JoinHelper.INSTANCE.createEntityJoin(
lhsQuerySpace,
attributeName,
rhs,
required,
attributeType,
fetchedPersister.getFactory()
);
lhsQuerySpace.addJoin( join );
}
return rhs;
}
public ExpandingCompositeQuerySpace makeCompositeQuerySpace(
ExpandingQuerySpace lhsQuerySpace,
CompositionDefinition compositionDefinition,
String querySpaceUid,
boolean shouldIncludeJoin) {
final boolean required = lhsQuerySpace.canJoinsBeRequired() && !compositionDefinition.isNullable();
return makeCompositeQuerySpace(
lhsQuerySpace,
new CompositePropertyMapping(
compositionDefinition.getType(),
lhsQuerySpace.getPropertyMapping(),
compositionDefinition.getName()
),
compositionDefinition.getName(),
compositionDefinition.getType(),
querySpaceUid,
required,
shouldIncludeJoin
);
}
public ExpandingCompositeQuerySpace makeCompositeQuerySpace(
ExpandingQuerySpace lhsQuerySpace,
CompositePropertyMapping compositePropertyMapping,
String attributeName,
CompositeType attributeType,
String querySpaceUid,
boolean required,
boolean shouldIncludeJoin) {
final ExpandingCompositeQuerySpace rhs = lhsQuerySpace.getExpandingQuerySpaces().makeCompositeQuerySpace(
querySpaceUid,
compositePropertyMapping,
required
);
if ( shouldIncludeJoin ) {
final JoinDefinedByMetadata join = JoinHelper.INSTANCE.createCompositeJoin(
lhsQuerySpace,
attributeName,
rhs,
required,
attributeType
);
lhsQuerySpace.addJoin( join );
}
return rhs;
}
public ExpandingCollectionQuerySpace makeCollectionQuerySpace(
ExpandingQuerySpace lhsQuerySpace,
AssociationAttributeDefinition attributeDefinition,
String querySpaceUid,
FetchStrategy fetchStrategy) {
final CollectionType fetchedType = (CollectionType) attributeDefinition.getType();
final CollectionPersister fetchedPersister = attributeDefinition.toCollectionDefinition().getCollectionPersister();
if ( fetchedPersister == null ) {
throw new WalkingException(
String.format(
"Unable to locate CollectionPersister [%s] for fetch [%s]",
fetchedType.getRole(),
attributeDefinition.getName()
)
);
}
final boolean required = lhsQuerySpace.canJoinsBeRequired() && !attributeDefinition.isNullable();
final ExpandingCollectionQuerySpace rhs = lhsQuerySpace.getExpandingQuerySpaces().makeCollectionQuerySpace(
querySpaceUid,
fetchedPersister,
required
);
if ( shouldIncludeJoin( fetchStrategy ) ) {
final JoinDefinedByMetadata join = JoinHelper.INSTANCE.createCollectionJoin(
lhsQuerySpace,
attributeDefinition.getName(),
rhs,
required,
(CollectionType) attributeDefinition.getType(),
fetchedPersister.getFactory()
);
lhsQuerySpace.addJoin( join );
}
return rhs;
}
public boolean shouldIncludeJoin(FetchStrategy fetchStrategy) {
return fetchStrategy.getTiming() == FetchTiming.IMMEDIATE && fetchStrategy.getStyle() == FetchStyle.JOIN;
}
}

View File

@ -105,8 +105,7 @@ public class QuerySpacesImpl implements ExpandingQuerySpaces {
entityPersister,
uid,
this,
canJoinsBeRequired,
sessionFactory
canJoinsBeRequired
);
registerQuerySpace( space );
@ -132,8 +131,7 @@ public class QuerySpacesImpl implements ExpandingQuerySpaces {
collectionPersister,
uid,
this,
canJoinsBeRequired,
sessionFactory
canJoinsBeRequired
);
registerQuerySpace( space );
@ -152,14 +150,18 @@ public class QuerySpacesImpl implements ExpandingQuerySpaces {
compositePropertyMapping,
uid,
this,
canJoinsBeRequired,
sessionFactory
canJoinsBeRequired
);
registerQuerySpace( space );
return space;
}
@Override
public SessionFactoryImplementor getSessionFactory() {
return sessionFactory;
}
private void checkQuerySpaceDoesNotExist(String uid) {
if ( querySpaceByUid.containsKey( uid ) ) {
throw new IllegalStateException( "Encountered duplicate QuerySpace uid : " + uid );

View File

@ -803,14 +803,18 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
attributeDefinition,
fetchStrategy
);
pushToStack( (ExpandingFetchSource) fetch );
if ( fetchStrategy.getStyle() == FetchStyle.JOIN ) {
pushToStack( (ExpandingFetchSource) fetch );
}
}
else {
// Collection
CollectionFetch fetch = currentSource.buildCollectionFetch( attributeDefinition, fetchStrategy );
pushToCollectionStack( fetch );
if ( fetchStrategy.getStyle() == FetchStyle.JOIN ) {
pushToCollectionStack( fetch );
}
}
return true;
return fetchStrategy.getStyle() == FetchStyle.JOIN;
}
protected abstract FetchStrategy determineFetchStrategy(AssociationAttributeDefinition attributeDefinition);

View File

@ -30,15 +30,5 @@ import org.hibernate.type.CompositeType;
/**
* @author Gail Badner
*/
public interface ExpandingCollectionQuerySpace extends CollectionQuerySpace {
public ExpandingEntityQuerySpace addIndexEntityQuerySpace(final EntityPersister elementPersister);
public ExpandingCompositeQuerySpace addIndexCompositeQuerySpace(CompositeType compositeType);
public ExpandingEntityQuerySpace addElementEntityQuerySpace(
final EntityPersister elementPersister);
public ExpandingCompositeQuerySpace addElementCompositeQuerySpace(
CompositeType compositeType);
public interface ExpandingCollectionQuerySpace extends CollectionQuerySpace, ExpandingQuerySpace {
}

View File

@ -28,5 +28,5 @@ import org.hibernate.loader.plan2.spi.CompositeQuerySpace;
/**
* @author Gail Badner
*/
public interface ExpandingCompositeQuerySpace extends CompositeQuerySpace, ExpandingSourceQuerySpace {
public interface ExpandingCompositeQuerySpace extends CompositeQuerySpace, ExpandingQuerySpace {
}

View File

@ -28,6 +28,6 @@ import org.hibernate.loader.plan2.spi.EntityQuerySpace;
/**
* @author Steve Ebersole
*/
public interface ExpandingEntityQuerySpace extends EntityQuerySpace, ExpandingSourceQuerySpace {
public interface ExpandingEntityQuerySpace extends EntityQuerySpace, ExpandingQuerySpace {
public ExpandingCompositeQuerySpace makeCompositeIdentifierQuerySpace();
}

View File

@ -23,34 +23,17 @@
*/
package org.hibernate.loader.plan2.build.spi;
import org.hibernate.loader.plan2.spi.Join;
import org.hibernate.loader.plan2.spi.QuerySpace;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.walking.spi.AttributeDefinition;
import org.hibernate.persister.walking.spi.CompositionDefinition;
/**
* @author Steve Ebersole
*/
public interface ExpandingSourceQuerySpace extends QuerySpace {
public interface ExpandingQuerySpace extends QuerySpace {
public ExpandingCompositeQuerySpace addCompositeQuerySpace(
CompositionDefinition compositionDefinition,
String querySpaceUid,
boolean shouldIncludeJoin);
public boolean canJoinsBeRequired();
public ExpandingEntityQuerySpace addEntityQuerySpace(
AttributeDefinition attributeDefinition,
EntityPersister persister,
String querySpaceUid,
boolean optional,
boolean shouldIncludeJoin);
public ExpandingCollectionQuerySpace addCollectionQuerySpace(
AttributeDefinition attributeDefinition,
CollectionPersister collectionPersister,
String querySpaceUid,
boolean shouldIncludeJoin);
public void addJoin(Join join);
public ExpandingQuerySpaces getExpandingQuerySpaces();
}

View File

@ -23,6 +23,7 @@
*/
package org.hibernate.loader.plan2.build.spi;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.plan2.build.internal.spaces.CompositePropertyMapping;
import org.hibernate.loader.plan2.spi.QuerySpaces;
import org.hibernate.persister.collection.CollectionPersister;
@ -56,4 +57,6 @@ public interface ExpandingQuerySpaces extends QuerySpaces {
String uid,
CompositePropertyMapping compositePropertyMapping,
boolean canJoinsBeRequired);
public SessionFactoryImplementor getSessionFactory();
}

View File

@ -23,7 +23,6 @@
*/
package org.hibernate.loader.plan2.spi;
import org.hibernate.type.AssociationType;
import org.hibernate.type.Type;
/**
@ -34,7 +33,7 @@ import org.hibernate.type.Type;
public interface JoinDefinedByMetadata extends Join {
/**
* Obtain the name of the property that defines the join, relative to the PropertyMapping
* ({@link org.hibernate.loader.plan2.spi.QuerySpace#getPropertyMapping()}) of the left-hand-side
* ({@link QuerySpace#toAliasedColumns(String, String)}) of the left-hand-side
* ({@link #getLeftHandSide()}) of the join
*
* @return The property name

View File

@ -57,6 +57,16 @@ public interface QuerySpace {
*/
public PropertyMapping getPropertyMapping();
/**
* Get the aliased column names for the specified property in the query space..
*
* @return the aliased column names for the specified property
* @param alias - the table alias
* @param propertyName - the property name
*/
public String[] toAliasedColumns(String alias, String propertyName);
/**
* Enumeration of the different types of QuerySpaces we can have.
*/

View File

@ -25,6 +25,9 @@ package org.hibernate.loader.plan2.spi;
import java.util.List;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.SessionFactoryImpl;
/**
* Models a collection of {@link QuerySpace} references and exposes the ability to find a {@link QuerySpace} by its UID
* <p/>