HHH-8276 - Integrate LoadPlans into UniqueEntityLoader (PoC)

This commit is contained in:
Strong Liu 2013-08-27 14:27:53 +08:00 committed by Steve Ebersole
parent 4defc8a5d6
commit 8638aac01a
10 changed files with 70 additions and 29 deletions

View File

@ -30,6 +30,7 @@ import java.util.Map;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.sql.Template; import org.hibernate.sql.Template;
/** /**
@ -51,30 +52,28 @@ public class FilterHelper {
* conditions are the values. * conditions are the values.
* *
* @param filters The map of defined filters. * @param filters The map of defined filters.
* @param dialect The sql dialect
* @param factory The session factory * @param factory The session factory
*/ */
public FilterHelper(List filters, SessionFactoryImplementor factory) { public FilterHelper(List<FilterConfiguration> filters, SessionFactoryImplementor factory) {
int filterCount = filters.size(); int filterCount = filters.size();
filterNames = new String[filterCount]; filterNames = new String[filterCount];
filterConditions = new String[filterCount]; filterConditions = new String[filterCount];
filterAutoAliasFlags = new boolean[filterCount]; filterAutoAliasFlags = new boolean[filterCount];
filterAliasTableMaps = new Map[filterCount]; filterAliasTableMaps = new Map[filterCount];
Iterator iter = filters.iterator();
filterCount = 0; filterCount = 0;
while ( iter.hasNext() ) { for ( final FilterConfiguration filter : filters ) {
filterAutoAliasFlags[filterCount] = false; filterAutoAliasFlags[filterCount] = false;
final FilterConfiguration filter = (FilterConfiguration) iter.next();
filterNames[filterCount] = filter.getName(); filterNames[filterCount] = filter.getName();
filterConditions[filterCount] = filter.getCondition(); filterConditions[filterCount] = filter.getCondition();
filterAliasTableMaps[filterCount] = filter.getAliasTableMap(factory); filterAliasTableMaps[filterCount] = filter.getAliasTableMap( factory );
if ((filterAliasTableMaps[filterCount].isEmpty() || isTableFromPersistentClass(filterAliasTableMaps[filterCount])) && filter.useAutoAliasInjection()){ if ( (filterAliasTableMaps[filterCount].isEmpty() || isTableFromPersistentClass( filterAliasTableMaps[filterCount] )) && filter
.useAutoAliasInjection() ) {
filterConditions[filterCount] = Template.renderWhereStringTemplate( filterConditions[filterCount] = Template.renderWhereStringTemplate(
filter.getCondition(), filter.getCondition(),
FilterImpl.MARKER, FilterImpl.MARKER,
factory.getDialect(), factory.getDialect(),
factory.getSqlFunctionRegistry() factory.getSqlFunctionRegistry()
); );
filterAutoAliasFlags[filterCount] = true; filterAutoAliasFlags[filterCount] = true;
} }
filterConditions[filterCount] = StringHelper.replace( filterConditions[filterCount] = StringHelper.replace(
@ -91,8 +90,8 @@ public class FilterHelper {
} }
public boolean isAffectedBy(Map enabledFilters) { public boolean isAffectedBy(Map enabledFilters) {
for ( int i = 0, max = filterNames.length; i < max; i++ ) { for ( String filterName : filterNames ) {
if ( enabledFilters.containsKey( filterNames[i] ) ) { if ( enabledFilters.containsKey( filterName ) ) {
return true; return true;
} }
} }
@ -106,13 +105,14 @@ public class FilterHelper {
} }
public void render(StringBuilder buffer, FilterAliasGenerator aliasGenerator, Map enabledFilters) { public void render(StringBuilder buffer, FilterAliasGenerator aliasGenerator, Map enabledFilters) {
if ( filterNames != null && filterNames.length > 0 ) { if ( CollectionHelper.isEmpty( filterNames ) ) {
for ( int i = 0, max = filterNames.length; i < max; i++ ) { return;
if ( enabledFilters.containsKey( filterNames[i] ) ) { }
final String condition = filterConditions[i]; for ( int i = 0, max = filterNames.length; i < max; i++ ) {
if ( StringHelper.isNotEmpty( condition ) ) { if ( enabledFilters.containsKey( filterNames[i] ) ) {
buffer.append(" and " ).append(render(aliasGenerator, i)); final String condition = filterConditions[i];
} if ( StringHelper.isNotEmpty( condition ) ) {
buffer.append( " and " ).append( render( aliasGenerator, i ) );
} }
} }
} }

View File

@ -159,6 +159,10 @@ public final class CollectionHelper {
return !isEmpty( map ); return !isEmpty( map );
} }
public static boolean isEmpty(Object[] objects){
return objects == null || objects.length==0;
}
public static <X,Y> Map<X, Y> makeCopy(Map<X, Y> map) { public static <X,Y> Map<X, Y> makeCopy(Map<X, Y> map) {
final Map<X,Y> copy = mapOfSize( map.size() + 1 ); final Map<X,Y> copy = mapOfSize( map.size() + 1 );
copy.putAll( map ); copy.putAll( map );

View File

@ -80,6 +80,7 @@ public class CollectionQuerySpaceImpl extends AbstractQuerySpace implements Coll
entityQuerySpace, entityQuerySpace,
// not sure this 'rhsColumnNames' bit is correct... // not sure this 'rhsColumnNames' bit is correct...
( (Queryable) indexPersister ).getKeyColumnNames(), ( (Queryable) indexPersister ).getKeyColumnNames(),
null,
required required
); );
internalGetJoins().add( join ); internalGetJoins().add( join );
@ -109,6 +110,7 @@ public class CollectionQuerySpaceImpl extends AbstractQuerySpace implements Coll
"index", "index",
compositeQuerySpace, compositeQuerySpace,
null, null,
null,
canJoinsBeRequired() canJoinsBeRequired()
); );
internalGetJoins().add( join ); internalGetJoins().add( join );
@ -135,6 +137,7 @@ public class CollectionQuerySpaceImpl extends AbstractQuerySpace implements Coll
"id", "id",
entityQuerySpace, entityQuerySpace,
( (Queryable) elementPersister ).getKeyColumnNames(), ( (Queryable) elementPersister ).getKeyColumnNames(),
null,
canJoinsBeRequired() canJoinsBeRequired()
); );
internalGetJoins().add( join ); internalGetJoins().add( join );
@ -166,6 +169,7 @@ public class CollectionQuerySpaceImpl extends AbstractQuerySpace implements Coll
"elements", "elements",
compositeQuerySpace, compositeQuerySpace,
null, null,
null,
canJoinsBeRequired() canJoinsBeRequired()
); );
internalGetJoins().add( join ); internalGetJoins().add( join );

View File

@ -32,6 +32,7 @@ import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.PropertyMapping; import org.hibernate.persister.entity.PropertyMapping;
import org.hibernate.persister.walking.spi.AttributeDefinition; import org.hibernate.persister.walking.spi.AttributeDefinition;
import org.hibernate.persister.walking.spi.CompositionDefinition; import org.hibernate.persister.walking.spi.CompositionDefinition;
import org.hibernate.type.AssociationType;
import org.hibernate.type.CollectionType; import org.hibernate.type.CollectionType;
import org.hibernate.type.EntityType; import org.hibernate.type.EntityType;
@ -90,6 +91,7 @@ public class CompositeQuerySpaceImpl extends AbstractQuerySpace implements Compo
propertyPath, propertyPath,
rhs, rhs,
null, null,
null,
required required
); );
internalGetJoins().add( join ); internalGetJoins().add( join );
@ -123,6 +125,7 @@ public class CompositeQuerySpaceImpl extends AbstractQuerySpace implements Compo
(EntityType) attributeDefinition.getType(), (EntityType) attributeDefinition.getType(),
sessionFactory() sessionFactory()
), ),
(EntityType) attributeDefinition.getType(),
required required
); );
internalGetJoins().add( join ); internalGetJoins().add( join );
@ -151,6 +154,7 @@ public class CompositeQuerySpaceImpl extends AbstractQuerySpace implements Compo
attributeDefinition.getName(), attributeDefinition.getName(),
rhs, rhs,
( (CollectionType) attributeDefinition.getType() ).getAssociatedJoinable( sessionFactory() ).getKeyColumnNames(), ( (CollectionType) attributeDefinition.getType() ).getAssociatedJoinable( sessionFactory() ).getKeyColumnNames(),
(AssociationType) attributeDefinition.getType(),
required required
); );
internalGetJoins().add( join ); internalGetJoins().add( join );

View File

@ -33,6 +33,7 @@ import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.PropertyMapping; import org.hibernate.persister.entity.PropertyMapping;
import org.hibernate.persister.walking.spi.AttributeDefinition; import org.hibernate.persister.walking.spi.AttributeDefinition;
import org.hibernate.persister.walking.spi.CompositionDefinition; import org.hibernate.persister.walking.spi.CompositionDefinition;
import org.hibernate.type.AssociationType;
import org.hibernate.type.CollectionType; import org.hibernate.type.CollectionType;
import org.hibernate.type.CompositeType; import org.hibernate.type.CompositeType;
import org.hibernate.type.EntityType; import org.hibernate.type.EntityType;
@ -92,6 +93,7 @@ public class EntityQuerySpaceImpl extends AbstractQuerySpace implements Expandin
compositionDefinition.getName(), compositionDefinition.getName(),
rhs, rhs,
null, null,
null,
required required
); );
internalGetJoins().add( join ); internalGetJoins().add( join );
@ -123,6 +125,7 @@ public class EntityQuerySpaceImpl extends AbstractQuerySpace implements Expandin
(EntityType) attribute.getType(), (EntityType) attribute.getType(),
sessionFactory() sessionFactory()
), ),
(AssociationType) attribute.getType(),
required required
); );
internalGetJoins().add( join ); internalGetJoins().add( join );
@ -151,6 +154,7 @@ public class EntityQuerySpaceImpl extends AbstractQuerySpace implements Expandin
attributeDefinition.getName(), attributeDefinition.getName(),
rhs, rhs,
( (CollectionType) attributeDefinition.getType() ).getAssociatedJoinable( sessionFactory() ).getKeyColumnNames(), ( (CollectionType) attributeDefinition.getType() ).getAssociatedJoinable( sessionFactory() ).getKeyColumnNames(),
(AssociationType) attributeDefinition.getType(),
required required
); );
internalGetJoins().add( join ); internalGetJoins().add( join );
@ -178,6 +182,7 @@ public class EntityQuerySpaceImpl extends AbstractQuerySpace implements Expandin
"id", "id",
rhs, rhs,
null, null,
null,
canJoinsBeRequired() canJoinsBeRequired()
); );
internalGetJoins().add( join ); internalGetJoins().add( join );

View File

@ -23,11 +23,10 @@
*/ */
package org.hibernate.loader.plan2.build.internal.spaces; package org.hibernate.loader.plan2.build.internal.spaces;
import org.hibernate.QueryException;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.loader.plan2.spi.JoinDefinedByMetadata; import org.hibernate.loader.plan2.spi.JoinDefinedByMetadata;
import org.hibernate.loader.plan2.spi.QuerySpace; import org.hibernate.loader.plan2.spi.QuerySpace;
import org.hibernate.persister.walking.spi.AttributeDefinition; import org.hibernate.type.AssociationType;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
@ -40,19 +39,21 @@ public class JoinImpl implements JoinDefinedByMetadata {
private final String[] rhsColumnNames; private final String[] rhsColumnNames;
private final boolean rightHandSideOptional; private final boolean rightHandSideOptional;
private final AssociationType joinedAssociationPropertyType;
public JoinImpl( public JoinImpl(
QuerySpace leftHandSide, QuerySpace leftHandSide,
String lhsPropertyName, String lhsPropertyName,
QuerySpace rightHandSide, QuerySpace rightHandSide,
String[] rhsColumnNames, String[] rhsColumnNames,
AssociationType attributeType,
boolean rightHandSideOptional) { boolean rightHandSideOptional) {
this.leftHandSide = leftHandSide; this.leftHandSide = leftHandSide;
this.lhsPropertyName = lhsPropertyName; this.lhsPropertyName = lhsPropertyName;
this.rightHandSide = rightHandSide; this.rightHandSide = rightHandSide;
this.rhsColumnNames = rhsColumnNames; this.rhsColumnNames = rhsColumnNames;
this.rightHandSideOptional = rightHandSideOptional; this.rightHandSideOptional = rightHandSideOptional;
this.joinedAssociationPropertyType = attributeType;
if ( StringHelper.isEmpty( lhsPropertyName ) ) { if ( StringHelper.isEmpty( lhsPropertyName ) ) {
throw new IllegalArgumentException( "Incoming 'lhsPropertyName' parameter was empty" ); throw new IllegalArgumentException( "Incoming 'lhsPropertyName' parameter was empty" );
} }
@ -101,4 +102,9 @@ public class JoinImpl implements JoinDefinedByMetadata {
public String getJoinedAssociationPropertyName() { public String getJoinedAssociationPropertyName() {
return lhsPropertyName; return lhsPropertyName;
} }
@Override
public AssociationType getJoinedAssociationPropertyType() {
return joinedAssociationPropertyType;
}
} }

View File

@ -47,6 +47,7 @@ import org.hibernate.loader.plan2.spi.EntityReference;
import org.hibernate.loader.plan2.spi.Fetch; import org.hibernate.loader.plan2.spi.Fetch;
import org.hibernate.loader.plan2.spi.FetchSource; import org.hibernate.loader.plan2.spi.FetchSource;
import org.hibernate.loader.plan2.spi.Join; import org.hibernate.loader.plan2.spi.Join;
import org.hibernate.loader.plan2.spi.JoinDefinedByMetadata;
import org.hibernate.loader.plan2.spi.QuerySpace; import org.hibernate.loader.plan2.spi.QuerySpace;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.collection.QueryableCollection; import org.hibernate.persister.collection.QueryableCollection;
@ -55,6 +56,7 @@ import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.persister.walking.internal.FetchStrategyHelper; import org.hibernate.persister.walking.internal.FetchStrategyHelper;
import org.hibernate.sql.JoinFragment; import org.hibernate.sql.JoinFragment;
import org.hibernate.sql.JoinType; import org.hibernate.sql.JoinType;
import org.hibernate.type.AssociationType;
/** /**
* Helper for implementors of entity and collection based query building based on LoadPlans providing common * Helper for implementors of entity and collection based query building based on LoadPlans providing common
@ -183,11 +185,12 @@ public class LoadQueryJoinAndFetchProcessor {
final String[] rhsColumnNames = join.resolveNonAliasedRightHandSideJoinConditionColumns(); final String[] rhsColumnNames = join.resolveNonAliasedRightHandSideJoinConditionColumns();
final String rhsTableAlias = aliases.getTableAlias(); final String rhsTableAlias = aliases.getTableAlias();
final AssociationType associationType = join instanceof JoinDefinedByMetadata ? ((JoinDefinedByMetadata)join).getJoinedAssociationPropertyType() : null;
final String additionalJoinConditions = resolveAdditionalJoinCondition( final String additionalJoinConditions = resolveAdditionalJoinCondition(
rhsTableAlias, rhsTableAlias,
join.getAnyAdditionalJoinConditions( rhsTableAlias ), join.getAnyAdditionalJoinConditions( rhsTableAlias ),
(Joinable) rightHandSide.getEntityPersister() (Joinable) rightHandSide.getEntityPersister(),
associationType
); );
final Joinable joinable = (Joinable) rightHandSide.getEntityPersister(); final Joinable joinable = (Joinable) rightHandSide.getEntityPersister();
@ -202,13 +205,15 @@ public class LoadQueryJoinAndFetchProcessor {
); );
} }
private String resolveAdditionalJoinCondition(String rhsTableAlias, String withClause, Joinable joinable) { private String resolveAdditionalJoinCondition(String rhsTableAlias, String withClause, Joinable joinable, AssociationType associationType) {
// turns out that the call to AssociationType#getOnCondition in the initial code really just translates to // turns out that the call to AssociationType#getOnCondition in the initial code really just translates to
// calls to the Joinable.filterFragment() method where the Joinable is either the entity or // calls to the Joinable.filterFragment() method where the Joinable is either the entity or
// collection persister // collection persister
final String filter = joinable.filterFragment( final String filter = associationType!=null?
rhsTableAlias, associationType.getOnCondition( rhsTableAlias, factory, buildingParameters.getQueryInfluencers().getEnabledFilters() ):
buildingParameters.getQueryInfluencers().getEnabledFilters() joinable.filterFragment(
rhsTableAlias,
buildingParameters.getQueryInfluencers().getEnabledFilters()
); );
if ( StringHelper.isEmpty( withClause ) && StringHelper.isEmpty( filter ) ) { if ( StringHelper.isEmpty( withClause ) && StringHelper.isEmpty( filter ) ) {
@ -432,11 +437,13 @@ public class LoadQueryJoinAndFetchProcessor {
// } // }
{ {
final AssociationType associationType = join instanceof JoinDefinedByMetadata ? ((JoinDefinedByMetadata)join).getJoinedAssociationPropertyType() : null;
// add join fragments from the collection table -> element entity table ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // add join fragments from the collection table -> element entity table ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
final String additionalJoinConditions = resolveAdditionalJoinCondition( final String additionalJoinConditions = resolveAdditionalJoinCondition(
elementTableAlias, elementTableAlias,
join.getAnyAdditionalJoinConditions( elementTableAlias ), join.getAnyAdditionalJoinConditions( elementTableAlias ),
queryableCollection queryableCollection,
associationType
); );
final String manyToManyFilter = persister.getManyToManyFilterFragment( final String manyToManyFilter = persister.getManyToManyFilterFragment(

View File

@ -33,8 +33,10 @@ import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreLogging;
import org.hibernate.loader.plan2.exec.process.spi.CollectionReferenceInitializer; import org.hibernate.loader.plan2.exec.process.spi.CollectionReferenceInitializer;
import org.hibernate.loader.plan2.exec.process.spi.ResultSetProcessingContext;
import org.hibernate.loader.plan2.exec.spi.CollectionReferenceAliases; import org.hibernate.loader.plan2.exec.spi.CollectionReferenceAliases;
import org.hibernate.loader.plan2.spi.CollectionReference; import org.hibernate.loader.plan2.spi.CollectionReference;
import org.hibernate.loader.plan2.spi.Fetch;
import org.hibernate.pretty.MessageHelper; import org.hibernate.pretty.MessageHelper;
/** /**
@ -153,7 +155,12 @@ public class CollectionReferenceInitializerImpl implements CollectionReferenceIn
} }
protected Serializable findCollectionOwnerKey(ResultSetProcessingContextImpl context) { protected Serializable findCollectionOwnerKey(ResultSetProcessingContextImpl context) {
return null; ResultSetProcessingContext.EntityReferenceProcessingState ownerState = context.getOwnerProcessingState( (Fetch) collectionReference );
if(ownerState == null || ownerState.getEntityKey()==null){
return null;
}
return ownerState.getEntityKey().getIdentifier();
} }
@Override @Override

View File

@ -23,6 +23,8 @@
*/ */
package org.hibernate.loader.plan2.spi; package org.hibernate.loader.plan2.spi;
import org.hibernate.type.AssociationType;
/** /**
* Specialization of a Join that is defined by the metadata. * Specialization of a Join that is defined by the metadata.
* *
@ -37,4 +39,5 @@ public interface JoinDefinedByMetadata extends Join {
* @return The property name * @return The property name
*/ */
public String getJoinedAssociationPropertyName(); public String getJoinedAssociationPropertyName();
public AssociationType getJoinedAssociationPropertyType();
} }

View File

@ -296,7 +296,8 @@ public class InterceptorTest extends BaseCoreFunctionalTestCase {
@Override @Override
public String onPrepareStatement(String sql) { public String onPrepareStatement(String sql) {
assertNotNull( sql ); assertNotNull( sql );
assertTrue( sql.toLowerCase().startsWith( expectedSQLs.poll().toLowerCase() ) ); String expectedSql = expectedSQLs.poll().toLowerCase();
assertTrue("sql:\n " + sql.toLowerCase() +"\n doesn't start with \n"+expectedSql+"\n", sql.toLowerCase().startsWith( expectedSql ) );
return sql; return sql;
} }
}; };