HHH-7841 - Redesign Loader

This commit is contained in:
Gail Badner 2013-05-21 03:08:47 -07:00
parent b846fa35b5
commit b282811527
3 changed files with 85 additions and 141 deletions

View File

@ -32,8 +32,8 @@ import org.hibernate.type.CompositeType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
/** /**
* This interface provides a delegate for a composite fetch owner to * A delegate for a composite fetch owner to obtain details about an
* obtain details about an owned sub-attribute fetch. * owned sub-attribute fetch.
* *
* @author Gail Badner * @author Gail Badner
*/ */

View File

@ -30,8 +30,8 @@ import org.hibernate.type.AssociationType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
/** /**
* This interface provides a delegate for an entity fetch owner to * A delegate for an entity fetch owner to obtain details about
* obtain details about an owned attribute fetch. * an owned attribute fetch.
* *
* @author Gail Badner * @author Gail Badner
*/ */
@ -59,6 +59,7 @@ public class EntityFetchOwnerDelegate implements FetchOwnerDelegate {
@Override @Override
public String[] getColumnNames(Fetch fetch) { public String[] getColumnNames(Fetch fetch) {
// TODO: cache this info
final OuterJoinLoadable outerJoinLoadable = (OuterJoinLoadable) entityPersister; final OuterJoinLoadable outerJoinLoadable = (OuterJoinLoadable) entityPersister;
Type fetchType = getType( fetch ); Type fetchType = getType( fetch );
if ( fetchType.isAssociationType() ) { if ( fetchType.isAssociationType() ) {
@ -75,6 +76,7 @@ public class EntityFetchOwnerDelegate implements FetchOwnerDelegate {
} }
private int determinePropertyIndex(Fetch fetch) { private int determinePropertyIndex(Fetch fetch) {
// TODO: cache this info
return entityPersister.getEntityMetamodel().getPropertyIndex( fetch.getOwnerPropertyName() ); return entityPersister.getEntityMetamodel().getPropertyIndex( fetch.getOwnerPropertyName() );
} }
} }

View File

@ -27,9 +27,7 @@ import java.io.Serializable;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
@ -44,8 +42,7 @@ import org.hibernate.engine.spi.EntityKey;
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.loader.PropertyPath; import org.hibernate.loader.PropertyPath;
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper; import org.hibernate.loader.plan.spi.AbstractFetchOwner;
import org.hibernate.loader.plan.spi.AbstractSingularAttributeFetch;
import org.hibernate.loader.plan.spi.CollectionFetch; import org.hibernate.loader.plan.spi.CollectionFetch;
import org.hibernate.loader.plan.spi.CollectionReference; import org.hibernate.loader.plan.spi.CollectionReference;
import org.hibernate.loader.plan.spi.CollectionReturn; import org.hibernate.loader.plan.spi.CollectionReturn;
@ -198,15 +195,10 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
final FetchOwner identifierAttributeCollector; final FetchOwner identifierAttributeCollector;
if ( entityIdentifierDefinition.isEncapsulated() ) { if ( entityIdentifierDefinition.isEncapsulated() ) {
if ( entityIdentifierDefinition.getEntityDefinition().getEntityPersister().getIdentifierType().isComponentType() ) { identifierAttributeCollector = new EncapsulatedIdentifierAttributeCollector( sessionFactory, entityReference );
identifierAttributeCollector = new EncapsulatedCompositeIdentifierAttributeCollector( entityReference );
}
else {
identifierAttributeCollector = new EncapsulatedIdentifierAttributeCollector( entityReference );
}
} }
else { else {
identifierAttributeCollector = new NonEncapsulatedIdentifierAttributeCollector( entityReference ); identifierAttributeCollector = new NonEncapsulatedIdentifierAttributeCollector( sessionFactory, entityReference );
} }
pushToStack( identifierAttributeCollector ); pushToStack( identifierAttributeCollector );
} }
@ -525,16 +517,14 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
public void poppedFromStack(); public void poppedFromStack();
} }
protected static abstract class AbstractIdentifierAttributeCollector protected static abstract class AbstractIdentifierAttributeCollector extends AbstractFetchOwner
implements FetchOwner, EntityReference, FetchStackAware { implements FetchOwner, EntityReference, FetchStackAware {
protected final EntityReference entityReference; protected final EntityReference entityReference;
protected final Map<Fetch,HydratedCompoundValueHandler> fetchToHydratedStateExtractorMap
= new HashMap<Fetch, HydratedCompoundValueHandler>();
protected final List<AbstractSingularAttributeFetch> identifierFetches = new ArrayList<AbstractSingularAttributeFetch>(); public AbstractIdentifierAttributeCollector(SessionFactoryImplementor sessionFactory, EntityReference entityReference) {
protected final Map<AbstractSingularAttributeFetch,HydratedCompoundValueHandler> fetchToHydratedStateExtractorMap super( sessionFactory );
= new HashMap<AbstractSingularAttributeFetch, HydratedCompoundValueHandler>();
public AbstractIdentifierAttributeCollector(EntityReference entityReference) {
this.entityReference = entityReference; this.entityReference = entityReference;
} }
@ -553,11 +543,6 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
return entityReference.getEntityPersister(); return entityReference.getEntityPersister();
} }
@Override
public boolean isNullable(Fetch fetch) {
return false;
}
@Override @Override
public IdentifierDescription getIdentifierDescription() { public IdentifierDescription getIdentifierDescription() {
return entityReference.getIdentifierDescription(); return entityReference.getIdentifierDescription();
@ -580,29 +565,24 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
// //
// IMPL NOTE: we pass ourselves as the FetchOwner which will route the fetch back through our #addFetch // IMPL NOTE: we pass ourselves as the FetchOwner which will route the fetch back through our #addFetch
// impl. We collect them there and later build the IdentifierDescription // impl. We collect them there and later build the IdentifierDescription
final EntityFetch fetch = LoadPlanBuildingHelper.buildStandardEntityFetch( final EntityFetch fetch = super.buildEntityFetch( attributeDefinition, fetchStrategy, loadPlanBuildingContext );
this,
attributeDefinition,
fetchStrategy,
loadPlanBuildingContext
);
fetchToHydratedStateExtractorMap.put( fetch, attributeDefinition.getHydratedCompoundValueExtractor() ); fetchToHydratedStateExtractorMap.put( fetch, attributeDefinition.getHydratedCompoundValueExtractor() );
return fetch; return fetch;
} }
@Override @Override
public CompositeFetch buildCompositeFetch( public Type getType(Fetch fetch) {
CompositionDefinition attributeDefinition, LoadPlanBuildingContext loadPlanBuildingContext) { if ( !fetch.getOwnerPropertyName().equals( entityReference.getEntityPersister().getIdentifierPropertyName() ) ) {
// nested composition. Unusual, but not disallowed. throw new IllegalArgumentException(
// String.format(
// IMPL NOTE: we pass ourselves as the FetchOwner which will route the fetch back through our #addFetch "Fetch owner property name [%s] is not the same as the identifier property name [%s].",
// impl. We collect them there and later build the IdentifierDescription fetch.getOwnerPropertyName(),
return LoadPlanBuildingHelper.buildStandardCompositeFetch( entityReference.getEntityPersister().getIdentifierPropertyName()
this, )
attributeDefinition, );
loadPlanBuildingContext }
); return super.getType( fetch );
} }
@Override @Override
@ -613,16 +593,6 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
protected abstract IdentifierDescription buildIdentifierDescription(); protected abstract IdentifierDescription buildIdentifierDescription();
@Override
public void addFetch(Fetch fetch) {
identifierFetches.add( (AbstractSingularAttributeFetch) fetch );
}
@Override
public Fetch[] getFetches() {
return ( (FetchOwner) entityReference ).getFetches();
}
@Override @Override
public void validateFetchPlan(FetchStrategy fetchStrategy) { public void validateFetchPlan(FetchStrategy fetchStrategy) {
( (FetchOwner) entityReference ).validateFetchPlan( fetchStrategy ); ( (FetchOwner) entityReference ).validateFetchPlan( fetchStrategy );
@ -641,38 +611,64 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
} }
} }
protected static abstract class AbstractCompositeIdentifierAttributeCollector extends AbstractIdentifierAttributeCollector {
public AbstractCompositeIdentifierAttributeCollector(EntityReference entityReference) {
super( entityReference );
}
}
protected static class EncapsulatedIdentifierAttributeCollector extends AbstractIdentifierAttributeCollector { protected static class EncapsulatedIdentifierAttributeCollector extends AbstractIdentifierAttributeCollector {
private final PropertyPath propertyPath; private final PropertyPath propertyPath;
private final FetchOwnerDelegate delegate;
public EncapsulatedIdentifierAttributeCollector(EntityReference entityReference) { public EncapsulatedIdentifierAttributeCollector(
super( entityReference ); final SessionFactoryImplementor sessionFactory,
final EntityReference entityReference) {
super( sessionFactory, entityReference );
this.propertyPath = ( (FetchOwner) entityReference ).getPropertyPath(); this.propertyPath = ( (FetchOwner) entityReference ).getPropertyPath();
final boolean isCompositeType = entityReference.getEntityPersister().getIdentifierType().isComponentType();
this.delegate = new FetchOwnerDelegate() {
@Override
public boolean isNullable(Fetch fetch) {
if ( !isCompositeType ) {
throw new IllegalStateException( "Non-composite ID cannot have fetches." );
}
return true;
}
@Override
public Type getType(Fetch fetch) {
if ( !isCompositeType ) {
throw new IllegalStateException( "Non-composite ID cannot have fetches." );
}
if ( !fetch.getOwnerPropertyName().equals( entityReference.getEntityPersister().getIdentifierPropertyName() ) ) {
throw new IllegalArgumentException(
String.format(
"Fetch owner property name [%s] is not the same as the identifier prop" +
fetch.getOwnerPropertyName(),
entityReference.getEntityPersister().getIdentifierPropertyName()
)
);
}
return entityReference.getEntityPersister().getIdentifierType();
}
@Override
public String[] getColumnNames(Fetch fetch) {
if ( !isCompositeType ) {
throw new IllegalStateException( "Non-composite ID cannot have fetches." );
}
return ( (Loadable) entityReference.getEntityPersister() ).getIdentifierColumnNames();
}
};
} }
@Override @Override
protected IdentifierDescription buildIdentifierDescription() { protected IdentifierDescription buildIdentifierDescription() {
return new IdentifierDescriptionImpl( return new IdentifierDescriptionImpl(
entityReference, entityReference,
identifierFetches.toArray( new AbstractSingularAttributeFetch[ identifierFetches.size() ] ), getFetches(),
null null
); );
} }
@Override @Override
public Type getType(Fetch fetch) { protected FetchOwnerDelegate getFetchOwnerDelegate() {
return null; //To change body of implemented methods use File | Settings | File Templates. return delegate;
}
@Override
public String[] getColumnNames(Fetch fetch) {
return ( (Loadable) entityReference.getEntityPersister() ).getIdentifierColumnNames();
} }
@Override @Override
@ -681,54 +677,12 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
} }
} }
protected static class EncapsulatedCompositeIdentifierAttributeCollector extends AbstractCompositeIdentifierAttributeCollector { protected static class NonEncapsulatedIdentifierAttributeCollector extends AbstractIdentifierAttributeCollector {
private final PropertyPath propertyPath;
public EncapsulatedCompositeIdentifierAttributeCollector(EntityReference entityReference) {
super( entityReference );
this.propertyPath = ( (FetchOwner) entityReference ).getPropertyPath();
}
@Override
protected IdentifierDescription buildIdentifierDescription() {
return new IdentifierDescriptionImpl(
entityReference,
identifierFetches.toArray( new AbstractSingularAttributeFetch[ identifierFetches.size() ] ),
null
);
}
@Override
public PropertyPath getPropertyPath() {
return propertyPath;
}
@Override
public Type getType(Fetch fetch) {
if ( !fetch.getOwnerPropertyName().equals( entityReference.getEntityPersister().getIdentifierPropertyName() ) ) {
throw new IllegalArgumentException(
String.format(
"Fetch owner property name [%s] is not the same as the identifier property name [%s].",
fetch.getOwnerPropertyName(),
entityReference.getEntityPersister().getIdentifierPropertyName()
)
);
}
return entityReference.getEntityPersister().getIdentifierType();
}
@Override
public String[] getColumnNames(Fetch fetch) {
return ( (Loadable) entityReference.getEntityPersister() ).getIdentifierColumnNames();
}
}
protected static class NonEncapsulatedIdentifierAttributeCollector extends AbstractCompositeIdentifierAttributeCollector {
private final PropertyPath propertyPath; private final PropertyPath propertyPath;
private final FetchOwnerDelegate fetchOwnerDelegate; private final FetchOwnerDelegate fetchOwnerDelegate;
public NonEncapsulatedIdentifierAttributeCollector(EntityReference entityReference) { public NonEncapsulatedIdentifierAttributeCollector(SessionFactoryImplementor sessionfactory, EntityReference entityReference) {
super( entityReference ); super( sessionfactory, entityReference );
this.propertyPath = ( (FetchOwner) entityReference ).getPropertyPath().append( "<id>" ); this.propertyPath = ( (FetchOwner) entityReference ).getPropertyPath().append( "<id>" );
this.fetchOwnerDelegate = new CompositeFetchOwnerDelegate( this.fetchOwnerDelegate = new CompositeFetchOwnerDelegate(
entityReference.getEntityPersister().getFactory(), entityReference.getEntityPersister().getFactory(),
@ -741,7 +695,7 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
protected IdentifierDescription buildIdentifierDescription() { protected IdentifierDescription buildIdentifierDescription() {
return new IdentifierDescriptionImpl( return new IdentifierDescriptionImpl(
entityReference, entityReference,
identifierFetches.toArray( new AbstractSingularAttributeFetch[ identifierFetches.size() ] ), getFetches(),
fetchToHydratedStateExtractorMap fetchToHydratedStateExtractorMap
); );
} }
@ -752,33 +706,21 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
} }
public Type getType(Fetch fetch) { @Override
if ( !fetch.getOwnerPropertyName().equals( entityReference.getEntityPersister().getIdentifierPropertyName() ) ) { protected FetchOwnerDelegate getFetchOwnerDelegate() {
throw new IllegalArgumentException( return fetchOwnerDelegate;
String.format(
"Fetch owner property name [%s] is not the same as the identifier property name [%s].",
fetch.getOwnerPropertyName(),
entityReference.getEntityPersister().getIdentifierPropertyName()
)
);
}
return fetchOwnerDelegate.getType( fetch );
}
public String[] getColumnNames(Fetch fetch) {
return fetchOwnerDelegate.getColumnNames( fetch );
} }
} }
private static class IdentifierDescriptionImpl implements IdentifierDescription { private static class IdentifierDescriptionImpl implements IdentifierDescription {
private final EntityReference entityReference; private final EntityReference entityReference;
private final AbstractSingularAttributeFetch[] identifierFetches; private final Fetch[] identifierFetches;
private final Map<AbstractSingularAttributeFetch,HydratedCompoundValueHandler> fetchToHydratedStateExtractorMap; private final Map<Fetch,HydratedCompoundValueHandler> fetchToHydratedStateExtractorMap;
private IdentifierDescriptionImpl( private IdentifierDescriptionImpl(
EntityReference entityReference, EntityReference entityReference,
AbstractSingularAttributeFetch[] identifierFetches, Fetch[] identifierFetches,
Map<AbstractSingularAttributeFetch, HydratedCompoundValueHandler> fetchToHydratedStateExtractorMap) { Map<Fetch, HydratedCompoundValueHandler> fetchToHydratedStateExtractorMap) {
this.entityReference = entityReference; this.entityReference = entityReference;
this.identifierFetches = identifierFetches; this.identifierFetches = identifierFetches;
this.fetchToHydratedStateExtractorMap = fetchToHydratedStateExtractorMap; this.fetchToHydratedStateExtractorMap = fetchToHydratedStateExtractorMap;
@ -796,7 +738,7 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
final Object ownerIdentifierHydratedState = ownerIdentifierResolutionContext.getHydratedForm(); final Object ownerIdentifierHydratedState = ownerIdentifierResolutionContext.getHydratedForm();
if ( ownerIdentifierHydratedState != null ) { if ( ownerIdentifierHydratedState != null ) {
for ( AbstractSingularAttributeFetch fetch : identifierFetches ) { for ( Fetch fetch : identifierFetches ) {
if ( fetch instanceof EntityFetch ) { if ( fetch instanceof EntityFetch ) {
final IdentifierResolutionContext identifierResolutionContext = final IdentifierResolutionContext identifierResolutionContext =
context.getIdentifierResolutionContext( (EntityFetch) fetch ); context.getIdentifierResolutionContext( (EntityFetch) fetch );
@ -833,7 +775,7 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
@Override @Override
public EntityKey resolve(ResultSet resultSet, ResultSetProcessingContext context) throws SQLException { public EntityKey resolve(ResultSet resultSet, ResultSetProcessingContext context) throws SQLException {
for ( AbstractSingularAttributeFetch fetch : identifierFetches ) { for ( Fetch fetch : identifierFetches ) {
resolveIdentifierFetch( resultSet, context, fetch ); resolveIdentifierFetch( resultSet, context, fetch );
} }
@ -850,7 +792,7 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
private static void resolveIdentifierFetch( private static void resolveIdentifierFetch(
ResultSet resultSet, ResultSet resultSet,
ResultSetProcessingContext context, ResultSetProcessingContext context,
AbstractSingularAttributeFetch fetch) throws SQLException { Fetch fetch) throws SQLException {
if ( fetch instanceof EntityFetch ) { if ( fetch instanceof EntityFetch ) {
EntityFetch entityFetch = (EntityFetch) fetch; EntityFetch entityFetch = (EntityFetch) fetch;
final IdentifierResolutionContext identifierResolutionContext = final IdentifierResolutionContext identifierResolutionContext =
@ -863,8 +805,8 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
identifierResolutionContext.registerEntityKey( fetchKey ); identifierResolutionContext.registerEntityKey( fetchKey );
} }
else if ( fetch instanceof CompositeFetch ) { else if ( fetch instanceof CompositeFetch ) {
for ( Fetch subFetch : fetch.getFetches() ) { for ( Fetch subFetch : ( (CompositeFetch) fetch ).getFetches() ) {
resolveIdentifierFetch( resultSet, context, (AbstractSingularAttributeFetch) subFetch ); resolveIdentifierFetch( resultSet, context, subFetch );
} }
} }
} }