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;
/**
* This interface provides a delegate for a composite fetch owner to
* obtain details about an owned sub-attribute fetch.
* A delegate for a composite fetch owner to obtain details about an
* owned sub-attribute fetch.
*
* @author Gail Badner
*/

View File

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

View File

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