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

View File

@ -80,6 +80,7 @@ public class CollectionQuerySpaceImpl extends AbstractQuerySpace implements Coll
entityQuerySpace,
// not sure this 'rhsColumnNames' bit is correct...
( (Queryable) indexPersister ).getKeyColumnNames(),
null,
required
);
internalGetJoins().add( join );
@ -109,6 +110,7 @@ public class CollectionQuerySpaceImpl extends AbstractQuerySpace implements Coll
"index",
compositeQuerySpace,
null,
null,
canJoinsBeRequired()
);
internalGetJoins().add( join );
@ -135,6 +137,7 @@ public class CollectionQuerySpaceImpl extends AbstractQuerySpace implements Coll
"id",
entityQuerySpace,
( (Queryable) elementPersister ).getKeyColumnNames(),
null,
canJoinsBeRequired()
);
internalGetJoins().add( join );
@ -166,6 +169,7 @@ public class CollectionQuerySpaceImpl extends AbstractQuerySpace implements Coll
"elements",
compositeQuerySpace,
null,
null,
canJoinsBeRequired()
);
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.walking.spi.AttributeDefinition;
import org.hibernate.persister.walking.spi.CompositionDefinition;
import org.hibernate.type.AssociationType;
import org.hibernate.type.CollectionType;
import org.hibernate.type.EntityType;
@ -90,6 +91,7 @@ public class CompositeQuerySpaceImpl extends AbstractQuerySpace implements Compo
propertyPath,
rhs,
null,
null,
required
);
internalGetJoins().add( join );
@ -123,6 +125,7 @@ public class CompositeQuerySpaceImpl extends AbstractQuerySpace implements Compo
(EntityType) attributeDefinition.getType(),
sessionFactory()
),
(EntityType) attributeDefinition.getType(),
required
);
internalGetJoins().add( join );
@ -151,6 +154,7 @@ public class CompositeQuerySpaceImpl extends AbstractQuerySpace implements Compo
attributeDefinition.getName(),
rhs,
( (CollectionType) attributeDefinition.getType() ).getAssociatedJoinable( sessionFactory() ).getKeyColumnNames(),
(AssociationType) attributeDefinition.getType(),
required
);
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.walking.spi.AttributeDefinition;
import org.hibernate.persister.walking.spi.CompositionDefinition;
import org.hibernate.type.AssociationType;
import org.hibernate.type.CollectionType;
import org.hibernate.type.CompositeType;
import org.hibernate.type.EntityType;
@ -92,6 +93,7 @@ public class EntityQuerySpaceImpl extends AbstractQuerySpace implements Expandin
compositionDefinition.getName(),
rhs,
null,
null,
required
);
internalGetJoins().add( join );
@ -123,6 +125,7 @@ public class EntityQuerySpaceImpl extends AbstractQuerySpace implements Expandin
(EntityType) attribute.getType(),
sessionFactory()
),
(AssociationType) attribute.getType(),
required
);
internalGetJoins().add( join );
@ -151,6 +154,7 @@ public class EntityQuerySpaceImpl extends AbstractQuerySpace implements Expandin
attributeDefinition.getName(),
rhs,
( (CollectionType) attributeDefinition.getType() ).getAssociatedJoinable( sessionFactory() ).getKeyColumnNames(),
(AssociationType) attributeDefinition.getType(),
required
);
internalGetJoins().add( join );
@ -178,6 +182,7 @@ public class EntityQuerySpaceImpl extends AbstractQuerySpace implements Expandin
"id",
rhs,
null,
null,
canJoinsBeRequired()
);
internalGetJoins().add( join );

View File

@ -23,11 +23,10 @@
*/
package org.hibernate.loader.plan2.build.internal.spaces;
import org.hibernate.QueryException;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.loader.plan2.spi.JoinDefinedByMetadata;
import org.hibernate.loader.plan2.spi.QuerySpace;
import org.hibernate.persister.walking.spi.AttributeDefinition;
import org.hibernate.type.AssociationType;
/**
* @author Steve Ebersole
@ -40,19 +39,21 @@ public class JoinImpl implements JoinDefinedByMetadata {
private final String[] rhsColumnNames;
private final boolean rightHandSideOptional;
private final AssociationType joinedAssociationPropertyType;
public JoinImpl(
QuerySpace leftHandSide,
String lhsPropertyName,
QuerySpace rightHandSide,
String[] rhsColumnNames,
AssociationType attributeType,
boolean rightHandSideOptional) {
this.leftHandSide = leftHandSide;
this.lhsPropertyName = lhsPropertyName;
this.rightHandSide = rightHandSide;
this.rhsColumnNames = rhsColumnNames;
this.rightHandSideOptional = rightHandSideOptional;
this.joinedAssociationPropertyType = attributeType;
if ( StringHelper.isEmpty( lhsPropertyName ) ) {
throw new IllegalArgumentException( "Incoming 'lhsPropertyName' parameter was empty" );
}
@ -101,4 +102,9 @@ public class JoinImpl implements JoinDefinedByMetadata {
public String getJoinedAssociationPropertyName() {
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.FetchSource;
import org.hibernate.loader.plan2.spi.Join;
import org.hibernate.loader.plan2.spi.JoinDefinedByMetadata;
import org.hibernate.loader.plan2.spi.QuerySpace;
import org.hibernate.persister.collection.CollectionPersister;
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.sql.JoinFragment;
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
@ -183,11 +185,12 @@ public class LoadQueryJoinAndFetchProcessor {
final String[] rhsColumnNames = join.resolveNonAliasedRightHandSideJoinConditionColumns();
final String rhsTableAlias = aliases.getTableAlias();
final AssociationType associationType = join instanceof JoinDefinedByMetadata ? ((JoinDefinedByMetadata)join).getJoinedAssociationPropertyType() : null;
final String additionalJoinConditions = resolveAdditionalJoinCondition(
rhsTableAlias,
join.getAnyAdditionalJoinConditions( rhsTableAlias ),
(Joinable) rightHandSide.getEntityPersister()
(Joinable) rightHandSide.getEntityPersister(),
associationType
);
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
// calls to the Joinable.filterFragment() method where the Joinable is either the entity or
// collection persister
final String filter = joinable.filterFragment(
rhsTableAlias,
buildingParameters.getQueryInfluencers().getEnabledFilters()
final String filter = associationType!=null?
associationType.getOnCondition( rhsTableAlias, factory, buildingParameters.getQueryInfluencers().getEnabledFilters() ):
joinable.filterFragment(
rhsTableAlias,
buildingParameters.getQueryInfluencers().getEnabledFilters()
);
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 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
final String additionalJoinConditions = resolveAdditionalJoinCondition(
elementTableAlias,
join.getAnyAdditionalJoinConditions( elementTableAlias ),
queryableCollection
queryableCollection,
associationType
);
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.internal.CoreLogging;
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.spi.CollectionReference;
import org.hibernate.loader.plan2.spi.Fetch;
import org.hibernate.pretty.MessageHelper;
/**
@ -153,7 +155,12 @@ public class CollectionReferenceInitializerImpl implements CollectionReferenceIn
}
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

View File

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

View File

@ -296,7 +296,8 @@ public class InterceptorTest extends BaseCoreFunctionalTestCase {
@Override
public String onPrepareStatement(String 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;
}
};