HHH-8276 - Integrate LoadPlans into UniqueEntityLoader (PoC)

This commit is contained in:
Steve Ebersole 2013-07-25 17:17:02 -05:00
parent b10c51eec7
commit f32c736160
19 changed files with 491 additions and 316 deletions

View File

@ -49,6 +49,7 @@ public abstract class BatchingEntityLoaderBuilder {
} }
default: { default: {
return org.hibernate.loader.entity.plan.LegacyBatchingEntityLoaderBuilder.INSTANCE; return org.hibernate.loader.entity.plan.LegacyBatchingEntityLoaderBuilder.INSTANCE;
// return LegacyBatchingEntityLoaderBuilder.INSTANCE;
} }
} }
} }

View File

@ -309,32 +309,32 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
// - the element graph pushed while starting would be popped in finishing/Entity/finishingComposite // - the element graph pushed while starting would be popped in finishing/Entity/finishingComposite
} }
@Override // @Override
public void startingCompositeCollectionElement(CompositeCollectionElementDefinition compositeElementDefinition) { // public void startingCompositeCollectionElement(CompositeCollectionElementDefinition compositeElementDefinition) {
log.tracef( // log.tracef(
"%s Starting composite collection element for (%s)", // "%s Starting composite collection element for (%s)",
StringHelper.repeat( ">>", fetchOwnerStack.size() ), // StringHelper.repeat( ">>", fetchOwnerStack.size() ),
compositeElementDefinition.getCollectionDefinition().getCollectionPersister().getRole() // compositeElementDefinition.getCollectionDefinition().getCollectionPersister().getRole()
); // );
} // }
//
@Override // @Override
public void finishingCompositeCollectionElement(CompositeCollectionElementDefinition compositeElementDefinition) { // public void finishingCompositeCollectionElement(CompositeCollectionElementDefinition compositeElementDefinition) {
// pop the current fetch owner, and make sure what we just popped represents this composition // // pop the current fetch owner, and make sure what we just popped represents this composition
final FetchOwner poppedFetchOwner = popFromStack(); // final FetchOwner poppedFetchOwner = popFromStack();
//
if ( ! CompositeElementGraph.class.isInstance( poppedFetchOwner ) ) { // if ( ! CompositeElementGraph.class.isInstance( poppedFetchOwner ) ) {
throw new WalkingException( "Mismatched FetchOwner from stack on pop" ); // throw new WalkingException( "Mismatched FetchOwner from stack on pop" );
} // }
//
// NOTE : not much else we can really check here atm since on the walking spi side we do not have path // // NOTE : not much else we can really check here atm since on the walking spi side we do not have path
//
log.tracef( // log.tracef(
"%s Finished composite element for : %s", // "%s Finished composite element for : %s",
StringHelper.repeat( "<<", fetchOwnerStack.size() ), // StringHelper.repeat( "<<", fetchOwnerStack.size() ),
compositeElementDefinition.getCollectionDefinition().getCollectionPersister().getRole() // compositeElementDefinition.getCollectionDefinition().getCollectionPersister().getRole()
); // );
} // }
@Override @Override
public void finishingCollection(CollectionDefinition collectionDefinition) { public void finishingCollection(CollectionDefinition collectionDefinition) {

View File

@ -39,21 +39,14 @@ public abstract class AbstractCompositeEntityIdentifierDescription
implements EntityIdentifierDescription, FetchSource, ExpandingEntityIdentifierDescription { implements EntityIdentifierDescription, FetchSource, ExpandingEntityIdentifierDescription {
private final EntityReference entityReference; private final EntityReference entityReference;
private final CompositeQuerySpace compositeQuerySpace;
protected AbstractCompositeEntityIdentifierDescription( protected AbstractCompositeEntityIdentifierDescription(
EntityReference entityReference, EntityReference entityReference,
CompositeQuerySpace compositeQuerySpace, CompositeQuerySpace compositeQuerySpace,
CompositeType identifierType, CompositeType identifierType,
PropertyPath propertyPath) { PropertyPath propertyPath) {
super( identifierType, propertyPath ); super( identifierType, compositeQuerySpace, false, propertyPath );
this.entityReference = entityReference; this.entityReference = entityReference;
this.compositeQuerySpace = compositeQuerySpace;
}
@Override
protected String getFetchLeftHandSideUid() {
return compositeQuerySpace.getUid();
} }
@Override @Override
@ -66,11 +59,4 @@ public abstract class AbstractCompositeEntityIdentifierDescription
// the source for this (as a Fetch) is the entity reference // the source for this (as a Fetch) is the entity reference
return (FetchSource) entityReference.getIdentifierDescription(); return (FetchSource) entityReference.getIdentifierDescription();
} }
@Override
public String getQuerySpaceUid() {
return compositeQuerySpace.getUid();
}
} }

View File

@ -35,6 +35,7 @@ import org.hibernate.loader.plan2.build.spi.ExpandingQuerySpace;
import org.hibernate.loader.plan2.build.spi.LoadPlanBuildingContext; import org.hibernate.loader.plan2.build.spi.LoadPlanBuildingContext;
import org.hibernate.loader.plan2.spi.CollectionFetch; import org.hibernate.loader.plan2.spi.CollectionFetch;
import org.hibernate.loader.plan2.spi.CompositeFetch; import org.hibernate.loader.plan2.spi.CompositeFetch;
import org.hibernate.loader.plan2.spi.CompositeQuerySpace;
import org.hibernate.loader.plan2.spi.EntityFetch; import org.hibernate.loader.plan2.spi.EntityFetch;
import org.hibernate.loader.plan2.spi.Fetch; import org.hibernate.loader.plan2.spi.Fetch;
import org.hibernate.loader.plan2.spi.Join; import org.hibernate.loader.plan2.spi.Join;
@ -56,16 +57,31 @@ public abstract class AbstractCompositeFetch implements CompositeFetch, Expandin
private static final FetchStrategy FETCH_STRATEGY = new FetchStrategy( FetchTiming.IMMEDIATE, FetchStyle.JOIN ); private static final FetchStrategy FETCH_STRATEGY = new FetchStrategy( FetchTiming.IMMEDIATE, FetchStyle.JOIN );
private final CompositeType compositeType; private final CompositeType compositeType;
private final CompositeQuerySpace compositeQuerySpace;
private final PropertyPath propertyPath; private final PropertyPath propertyPath;
private final boolean allowCollectionFetches;
private List<Fetch> fetches; private List<Fetch> fetches;
protected AbstractCompositeFetch(CompositeType compositeType, PropertyPath propertyPath) { protected AbstractCompositeFetch(
CompositeType compositeType,
CompositeQuerySpace compositeQuerySpace,
boolean allowCollectionFetches, PropertyPath propertyPath) {
this.compositeType = compositeType; this.compositeType = compositeType;
this.compositeQuerySpace = compositeQuerySpace;
this.allowCollectionFetches = allowCollectionFetches;
this.propertyPath = propertyPath; this.propertyPath = propertyPath;
} }
protected abstract String getFetchLeftHandSideUid(); @SuppressWarnings("UnusedParameters")
protected CompositeQuerySpace resolveCompositeQuerySpace(LoadPlanBuildingContext loadPlanBuildingContext) {
return compositeQuerySpace;
}
@Override
public String getQuerySpaceUid() {
return compositeQuerySpace.getUid();
}
@Override @Override
public void validateFetchPlan(FetchStrategy fetchStrategy, AttributeDefinition attributeDefinition) { public void validateFetchPlan(FetchStrategy fetchStrategy, AttributeDefinition attributeDefinition) {
@ -92,8 +108,8 @@ public abstract class AbstractCompositeFetch implements CompositeFetch, Expandin
); );
} }
final ExpandingQuerySpace leftHandSide = (ExpandingQuerySpace) loadPlanBuildingContext.getQuerySpaces().getQuerySpaceByUid( final ExpandingQuerySpace leftHandSide = (ExpandingQuerySpace) resolveCompositeQuerySpace(
getFetchLeftHandSideUid() loadPlanBuildingContext
); );
final Join join = leftHandSide.addEntityJoin( final Join join = leftHandSide.addEntityJoin(
attributeDefinition, attributeDefinition,
@ -122,11 +138,18 @@ public abstract class AbstractCompositeFetch implements CompositeFetch, Expandin
public CompositeFetch buildCompositeFetch( public CompositeFetch buildCompositeFetch(
CompositionDefinition attributeDefinition, CompositionDefinition attributeDefinition,
LoadPlanBuildingContext loadPlanBuildingContext) { LoadPlanBuildingContext loadPlanBuildingContext) {
final ExpandingQuerySpace leftHandSide = (ExpandingQuerySpace) resolveCompositeQuerySpace( loadPlanBuildingContext );
final Join join = leftHandSide.addCompositeJoin(
attributeDefinition,
loadPlanBuildingContext.getQuerySpaces().generateImplicitUid()
);
final NestedCompositeFetchImpl fetch = new NestedCompositeFetchImpl( final NestedCompositeFetchImpl fetch = new NestedCompositeFetchImpl(
this, this,
attributeDefinition.getType(), attributeDefinition.getType(),
getPropertyPath(), (CompositeQuerySpace) join.getRightHandSide(),
getFetchLeftHandSideUid() allowCollectionFetches,
getPropertyPath()
); );
addFetch( fetch ); addFetch( fetch );
return fetch; return fetch;
@ -137,6 +160,15 @@ public abstract class AbstractCompositeFetch implements CompositeFetch, Expandin
AssociationAttributeDefinition attributeDefinition, AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy, FetchStrategy fetchStrategy,
LoadPlanBuildingContext loadPlanBuildingContext) { LoadPlanBuildingContext loadPlanBuildingContext) {
if ( !allowCollectionFetches ) {
throw new WalkingException(
String.format(
"This composite path [%s] does not allow collection fetches (composite id or composite collection index/element",
propertyPath.getFullPath()
)
);
}
// general question here wrt Joins and collection fetches... do we create multiple Joins for many-to-many, // 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? // for example, or do we allow the Collection QuerySpace to handle that?

View File

@ -69,7 +69,7 @@ public abstract class AbstractEntityReference implements EntityReference, Expand
PropertyPath propertyPath) { PropertyPath propertyPath) {
this.entityQuerySpace = entityQuerySpace; this.entityQuerySpace = entityQuerySpace;
this.propertyPath = propertyPath; this.propertyPath = propertyPath;
this.identifierDescription = buildIdentifierDescription( entityQuerySpace ); this.identifierDescription = buildIdentifierDescription();
} }
@ -77,11 +77,9 @@ public abstract class AbstractEntityReference implements EntityReference, Expand
* Builds just the first level of identifier description. This will be either a simple id descriptor (String, * Builds just the first level of identifier description. This will be either a simple id descriptor (String,
* Long, etc) or some form of composite id (either encapsulated or not). * Long, etc) or some form of composite id (either encapsulated or not).
* *
* @param querySpace The entity query space
*
* @return the descriptor for the identifier * @return the descriptor for the identifier
*/ */
private EntityIdentifierDescription buildIdentifierDescription(EntityQuerySpace querySpace) { private EntityIdentifierDescription buildIdentifierDescription() {
final EntityPersister persister = entityQuerySpace.getEntityPersister(); final EntityPersister persister = entityQuerySpace.getEntityPersister();
final EntityIdentifierDefinition identifierDefinition = persister.getEntityKeyDefinition(); final EntityIdentifierDefinition identifierDefinition = persister.getEntityKeyDefinition();
@ -166,9 +164,8 @@ public abstract class AbstractEntityReference implements EntityReference, Expand
) )
); );
} }
final ExpandingQuerySpace leftHandSide = (ExpandingQuerySpace) loadPlanBuildingContext.getQuerySpaces().getQuerySpaceByUid(
getQuerySpaceUid() final ExpandingQuerySpace leftHandSide = (ExpandingQuerySpace) entityQuerySpace;
);
final Join join = leftHandSide.addEntityJoin( final Join join = leftHandSide.addEntityJoin(
attributeDefinition, attributeDefinition,
fetchedPersister, fetchedPersister,
@ -196,9 +193,17 @@ public abstract class AbstractEntityReference implements EntityReference, Expand
public CompositeFetch buildCompositeFetch( public CompositeFetch buildCompositeFetch(
CompositionDefinition attributeDefinition, CompositionDefinition attributeDefinition,
LoadPlanBuildingContext loadPlanBuildingContext) { LoadPlanBuildingContext loadPlanBuildingContext) {
final ExpandingQuerySpace leftHandSide = (ExpandingQuerySpace) entityQuerySpace;
final Join join = leftHandSide.addCompositeJoin(
attributeDefinition,
loadPlanBuildingContext.getQuerySpaces().generateImplicitUid()
);
final CompositeFetchImpl fetch = new CompositeFetchImpl( final CompositeFetchImpl fetch = new CompositeFetchImpl(
this, this,
attributeDefinition.getType(), attributeDefinition.getType(),
(CompositeQuerySpace) join.getRightHandSide(),
true,
getPropertyPath() getPropertyPath()
); );
addFetch( fetch ); addFetch( fetch );

View File

@ -23,19 +23,17 @@
*/ */
package org.hibernate.loader.plan2.build.internal.returns; package org.hibernate.loader.plan2.build.internal.returns;
import org.hibernate.engine.FetchStrategy;
import org.hibernate.loader.plan2.build.spi.LoadPlanBuildingContext;
import org.hibernate.loader.plan2.spi.CollectionFetch;
import org.hibernate.loader.plan2.spi.CollectionFetchableElement; import org.hibernate.loader.plan2.spi.CollectionFetchableElement;
import org.hibernate.loader.plan2.spi.CollectionReference; import org.hibernate.loader.plan2.spi.CollectionReference;
import org.hibernate.loader.plan2.spi.CompositeFetch; import org.hibernate.loader.plan2.spi.CompositeFetch;
import org.hibernate.loader.plan2.spi.CompositeQuerySpace;
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.persister.walking.spi.AssociationAttributeDefinition;
import org.hibernate.persister.walking.spi.WalkingException;
import org.hibernate.type.CompositeType; import org.hibernate.type.CompositeType;
/** /**
* Models the element graph of a collection, where the elements are composite
*
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class CollectionFetchableElementCompositeGraph public class CollectionFetchableElementCompositeGraph
@ -43,23 +41,16 @@ public class CollectionFetchableElementCompositeGraph
implements CompositeFetch, CollectionFetchableElement { implements CompositeFetch, CollectionFetchableElement {
private final CollectionReference collectionReference; private final CollectionReference collectionReference;
private final Join compositeJoin;
public CollectionFetchableElementCompositeGraph( public CollectionFetchableElementCompositeGraph(CollectionReference collectionReference, Join compositeJoin) {
CollectionReference collectionReference,
Join compositeJoin) {
super( super(
(CompositeType) compositeJoin.getRightHandSide().getPropertyMapping().getType(), (CompositeType) compositeJoin.getRightHandSide().getPropertyMapping().getType(),
(CompositeQuerySpace) compositeJoin.getRightHandSide(),
false,
// these property paths are just informational... // these property paths are just informational...
collectionReference.getPropertyPath().append( "<element>" ) collectionReference.getPropertyPath().append( "<element>" )
); );
this.collectionReference = collectionReference; this.collectionReference = collectionReference;
this.compositeJoin = compositeJoin;
}
@Override
protected String getFetchLeftHandSideUid() {
return compositeJoin.getRightHandSide().getUid();
} }
@Override @Override
@ -71,17 +62,4 @@ public class CollectionFetchableElementCompositeGraph
public FetchSource getSource() { public FetchSource getSource() {
return collectionReference.getElementGraph(); return collectionReference.getElementGraph();
} }
@Override
public CollectionFetch buildCollectionFetch(
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy,
LoadPlanBuildingContext loadPlanBuildingContext) {
throw new WalkingException( "Encountered collection as part of fetched Collection composite-element" );
}
@Override
public String getQuerySpaceUid() {
return compositeJoin.getLeftHandSide().getUid();
}
} }

View File

@ -23,21 +23,19 @@
*/ */
package org.hibernate.loader.plan2.build.internal.returns; package org.hibernate.loader.plan2.build.internal.returns;
import org.hibernate.engine.FetchStrategy;
import org.hibernate.loader.plan2.build.spi.LoadPlanBuildingContext;
import org.hibernate.loader.plan2.spi.CollectionFetch;
import org.hibernate.loader.plan2.spi.CollectionFetchableIndex; import org.hibernate.loader.plan2.spi.CollectionFetchableIndex;
import org.hibernate.loader.plan2.spi.CollectionReference; import org.hibernate.loader.plan2.spi.CollectionReference;
import org.hibernate.loader.plan2.spi.CompositeFetch; import org.hibernate.loader.plan2.spi.CompositeFetch;
import org.hibernate.loader.plan2.spi.CompositeQuerySpace;
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.persister.walking.spi.AssociationAttributeDefinition;
import org.hibernate.persister.walking.spi.AttributeDefinition;
import org.hibernate.persister.walking.spi.WalkingException;
import org.hibernate.type.CompositeType; import org.hibernate.type.CompositeType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
/** /**
* Models the index graph of a collection, where the index are composite. This can only be a Map, where the keys are
* composite
*
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class CollectionFetchableIndexCompositeGraph public class CollectionFetchableIndexCompositeGraph
@ -45,17 +43,17 @@ public class CollectionFetchableIndexCompositeGraph
implements CompositeFetch, CollectionFetchableIndex { implements CompositeFetch, CollectionFetchableIndex {
private final CollectionReference collectionReference; private final CollectionReference collectionReference;
private final Join compositeJoin;
public CollectionFetchableIndexCompositeGraph( public CollectionFetchableIndexCompositeGraph(
CollectionReference collectionReference, CollectionReference collectionReference,
Join compositeJoin) { Join compositeJoin) {
super( super(
extractIndexType( compositeJoin ), extractIndexType( compositeJoin ),
(CompositeQuerySpace) compositeJoin.getRightHandSide(),
false,
collectionReference.getPropertyPath().append( "<index>" ) collectionReference.getPropertyPath().append( "<index>" )
); );
this.collectionReference = collectionReference; this.collectionReference = collectionReference;
this.compositeJoin = compositeJoin;
} }
private static CompositeType extractIndexType(Join compositeJoin) { private static CompositeType extractIndexType(Join compositeJoin) {
@ -67,12 +65,6 @@ public class CollectionFetchableIndexCompositeGraph
throw new IllegalArgumentException( "Could note extract collection composite-index" ); throw new IllegalArgumentException( "Could note extract collection composite-index" );
} }
@Override
protected String getFetchLeftHandSideUid() {
return compositeJoin.getRightHandSide().getUid();
}
@Override @Override
public CollectionReference getCollectionReference() { public CollectionReference getCollectionReference() {
return collectionReference; return collectionReference;
@ -82,24 +74,4 @@ public class CollectionFetchableIndexCompositeGraph
public FetchSource getSource() { public FetchSource getSource() {
return collectionReference.getIndexGraph(); return collectionReference.getIndexGraph();
} }
@Override
public void validateFetchPlan(FetchStrategy fetchStrategy, AttributeDefinition attributeDefinition) {
// metamodel should already disallow collections to be defined as part of a collection composite-index
// so, nothing to do here
super.validateFetchPlan( fetchStrategy, attributeDefinition );
}
@Override
public CollectionFetch buildCollectionFetch(
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy,
LoadPlanBuildingContext loadPlanBuildingContext) {
throw new WalkingException( "Encountered collection as part of the Map composite-index" );
}
@Override
public String getQuerySpaceUid() {
return compositeJoin.getRightHandSide().getUid();
}
} }

View File

@ -25,7 +25,7 @@ package org.hibernate.loader.plan2.build.internal.returns;
import org.hibernate.loader.PropertyPath; import org.hibernate.loader.PropertyPath;
import org.hibernate.loader.plan2.spi.CompositeFetch; import org.hibernate.loader.plan2.spi.CompositeFetch;
import org.hibernate.loader.plan2.spi.EntityReference; import org.hibernate.loader.plan2.spi.CompositeQuerySpace;
import org.hibernate.loader.plan2.spi.FetchSource; import org.hibernate.loader.plan2.spi.FetchSource;
import org.hibernate.type.CompositeType; import org.hibernate.type.CompositeType;
@ -33,28 +33,20 @@ import org.hibernate.type.CompositeType;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class CompositeFetchImpl extends AbstractCompositeFetch implements CompositeFetch { public class CompositeFetchImpl extends AbstractCompositeFetch implements CompositeFetch {
private final EntityReference source; private final FetchSource source;
protected CompositeFetchImpl( protected CompositeFetchImpl(
EntityReference source, FetchSource source,
CompositeType compositeType, CompositeType compositeType,
CompositeQuerySpace compositeQuerySpace,
boolean allowCollectionFetches,
PropertyPath propertyPath) { PropertyPath propertyPath) {
super( compositeType, propertyPath ); super( compositeType, compositeQuerySpace, allowCollectionFetches, propertyPath );
this.source = source; this.source = source;
} }
@Override
protected String getFetchLeftHandSideUid() {
return getSource().getQuerySpaceUid();
}
@Override @Override
public FetchSource getSource() { public FetchSource getSource() {
return source; return source;
} }
@Override
public String getQuerySpaceUid() {
return source.getQuerySpaceUid();
}
} }

View File

@ -30,15 +30,28 @@ import org.hibernate.loader.plan2.spi.EntityReference;
import org.hibernate.type.CompositeType; import org.hibernate.type.CompositeType;
/** /**
* Models a composite entity identifier that is encapsulated (meaning there is a composite class and a single
* attribute that encapsulates the composite value).
*
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class EncapsulatedEntityIdentifierDescription public class EncapsulatedEntityIdentifierDescription
extends AbstractCompositeEntityIdentifierDescription extends AbstractCompositeEntityIdentifierDescription
implements ExpandingEntityIdentifierDescription { implements ExpandingEntityIdentifierDescription {
/**
* Build an encapsulated version of a composite EntityIdentifierDescription
*
* @param entityReference The entity whose identifier we describe
* @param compositeQuerySpace The query space we are mapped to.
* @param compositeType The type representing this composition
* @param propertyPath The property path (informational)
*/
protected EncapsulatedEntityIdentifierDescription( protected EncapsulatedEntityIdentifierDescription(
EntityReference entityReference, EntityReference entityReference,
CompositeQuerySpace compositeQuerySpace, CompositeQuerySpace compositeQuerySpace,
CompositeType identifierType, PropertyPath propertyPath) { CompositeType compositeType,
super( entityReference, compositeQuerySpace, identifierType, propertyPath ); PropertyPath propertyPath) {
super( entityReference, compositeQuerySpace, compositeType, propertyPath );
} }
} }

View File

@ -25,6 +25,7 @@ package org.hibernate.loader.plan2.build.internal.returns;
import org.hibernate.loader.PropertyPath; import org.hibernate.loader.PropertyPath;
import org.hibernate.loader.plan2.spi.CompositeFetch; import org.hibernate.loader.plan2.spi.CompositeFetch;
import org.hibernate.loader.plan2.spi.CompositeQuerySpace;
import org.hibernate.loader.plan2.spi.FetchSource; import org.hibernate.loader.plan2.spi.FetchSource;
import org.hibernate.type.CompositeType; import org.hibernate.type.CompositeType;
@ -33,30 +34,18 @@ import org.hibernate.type.CompositeType;
*/ */
public class NestedCompositeFetchImpl extends AbstractCompositeFetch { public class NestedCompositeFetchImpl extends AbstractCompositeFetch {
private final CompositeFetch source; private final CompositeFetch source;
private final String fetchLeftHandSideUid;
public NestedCompositeFetchImpl( public NestedCompositeFetchImpl(
CompositeFetch source, CompositeFetch source,
CompositeType type, CompositeType type,
PropertyPath propertyPath, CompositeQuerySpace compositeQuerySpace,
String fetchLeftHandSideUid) { boolean allowCollectionFetches, PropertyPath propertyPath) {
super( type, propertyPath ); super( type, compositeQuerySpace, allowCollectionFetches, propertyPath );
this.source = source; this.source = source;
this.fetchLeftHandSideUid = fetchLeftHandSideUid;
}
@Override
protected String getFetchLeftHandSideUid() {
return fetchLeftHandSideUid;
} }
@Override @Override
public FetchSource getSource() { public FetchSource getSource() {
return source; return source;
} }
@Override
public String getQuerySpaceUid() {
return source.getQuerySpaceUid();
}
} }

View File

@ -29,9 +29,20 @@ import org.hibernate.loader.plan2.spi.EntityReference;
import org.hibernate.type.CompositeType; import org.hibernate.type.CompositeType;
/** /**
* Models a composite entity identifier that is non-encapsulated (meaning there is no composite class, no
* single attribute that encapsulates the composite value).
*
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class NonEncapsulatedEntityIdentifierDescription extends AbstractCompositeEntityIdentifierDescription { public class NonEncapsulatedEntityIdentifierDescription extends AbstractCompositeEntityIdentifierDescription {
/**
* Build a non-encapsulated version of a composite EntityIdentifierDescription
*
* @param entityReference The entity whose identifier we describe
* @param compositeQuerySpace The query space we are mapped to.
* @param compositeType The type representing this composition
* @param propertyPath The property path (informational)
*/
public NonEncapsulatedEntityIdentifierDescription( public NonEncapsulatedEntityIdentifierDescription(
EntityReference entityReference, EntityReference entityReference,
CompositeQuerySpace compositeQuerySpace, CompositeQuerySpace compositeQuerySpace,

View File

@ -58,7 +58,6 @@ import org.hibernate.persister.walking.spi.AttributeDefinition;
import org.hibernate.persister.walking.spi.CollectionDefinition; import org.hibernate.persister.walking.spi.CollectionDefinition;
import org.hibernate.persister.walking.spi.CollectionElementDefinition; import org.hibernate.persister.walking.spi.CollectionElementDefinition;
import org.hibernate.persister.walking.spi.CollectionIndexDefinition; import org.hibernate.persister.walking.spi.CollectionIndexDefinition;
import org.hibernate.persister.walking.spi.CompositeCollectionElementDefinition;
import org.hibernate.persister.walking.spi.CompositionDefinition; import org.hibernate.persister.walking.spi.CompositionDefinition;
import org.hibernate.persister.walking.spi.EntityDefinition; import org.hibernate.persister.walking.spi.EntityDefinition;
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition; import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
@ -201,7 +200,13 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
final ExpandingFetchSource fetchSource = popFromStack(); final ExpandingFetchSource fetchSource = popFromStack();
if ( ! EntityReference.class.isInstance( fetchSource ) ) { if ( ! EntityReference.class.isInstance( fetchSource ) ) {
throw new WalkingException( "Mismatched FetchSource from stack on pop" ); throw new WalkingException(
String.format(
"Mismatched FetchSource from stack on pop. Expecting EntityReference(%s), but found %s",
entityDefinition.getEntityPersister().getEntityName(),
fetchSource
)
);
} }
final EntityReference entityReference = (EntityReference) fetchSource; final EntityReference entityReference = (EntityReference) fetchSource;
@ -366,39 +371,79 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
} }
@Override @Override
public void startingCollectionIndex(CollectionIndexDefinition collectionIndexDefinition) { public void startingCollectionIndex(CollectionIndexDefinition indexDefinition) {
final Type indexType = collectionIndexDefinition.getType(); final Type indexType = indexDefinition.getType();
if ( indexType.isAssociationType() || indexType.isComponentType() ) { if ( indexType.isAnyType() ) {
throw new WalkingException( "CollectionIndexDefinition reported any-type mapping as map index" );
}
log.tracef(
"%s Starting collection index graph : %s",
StringHelper.repeat( ">>", fetchSourceStack.size() ),
indexDefinition.getCollectionDefinition().getCollectionPersister().getRole()
);
final CollectionReference collectionReference = collectionReferenceStack.peekFirst(); final CollectionReference collectionReference = collectionReferenceStack.peekFirst();
final CollectionFetchableIndex indexGraph = collectionReference.getIndexGraph(); final CollectionFetchableIndex indexGraph = collectionReference.getIndexGraph();
if ( indexType.isEntityType() || indexType.isComponentType() ) {
if ( indexGraph == null ) { if ( indexGraph == null ) {
throw new WalkingException( "Collection reference did not return index handler" ); throw new WalkingException(
"CollectionReference did not return an expected index graph : " +
indexDefinition.getCollectionDefinition().getCollectionPersister().getRole()
);
} }
pushToStack( (ExpandingFetchSource) indexGraph ); pushToStack( (ExpandingFetchSource) indexGraph );
} }
else {
if ( indexGraph != null ) {
throw new WalkingException(
"CollectionReference returned an unexpected index graph : " +
indexDefinition.getCollectionDefinition().getCollectionPersister().getRole()
);
}
}
} }
@Override @Override
public void finishingCollectionIndex(CollectionIndexDefinition collectionIndexDefinition) { public void finishingCollectionIndex(CollectionIndexDefinition indexDefinition) {
// nothing to do here final Type indexType = indexDefinition.getType();
// - the element graph pushed while starting would be popped in finishingEntity/finishingComposite if ( indexType.isComponentType() ) {
// todo : validate the stack?
popFromStack();
}
// entity indexes would be popped during finishingEntity processing
log.tracef(
"%s Finished collection index graph : %s",
StringHelper.repeat( "<<", fetchSourceStack.size() ),
indexDefinition.getCollectionDefinition().getCollectionPersister().getRole()
);
} }
@Override @Override
public void startingCollectionElements(CollectionElementDefinition elementDefinition) { public void startingCollectionElements(CollectionElementDefinition elementDefinition) {
final Type elementType = elementDefinition.getType();
if ( elementType.isAnyType() ) {
return;
}
log.tracef(
"%s Starting collection element graph : %s",
StringHelper.repeat( ">>", fetchSourceStack.size() ),
elementDefinition.getCollectionDefinition().getCollectionPersister().getRole()
);
final CollectionReference collectionReference = collectionReferenceStack.peekFirst(); final CollectionReference collectionReference = collectionReferenceStack.peekFirst();
final CollectionFetchableElement elementGraph = collectionReference.getElementGraph(); final CollectionFetchableElement elementGraph = collectionReference.getElementGraph();
final Type elementType = elementDefinition.getType(); if ( elementType.isAssociationType() || elementType.isComponentType() ) {
final boolean expectFetchSourceElements =
( elementType.isAssociationType() || elementType.isComponentType() )
&& ! elementType.isAnyType();
if ( expectFetchSourceElements ) {
if ( elementGraph == null ) { if ( elementGraph == null ) {
throw new IllegalStateException( throw new IllegalStateException(
"Expecting CollectionFetchableElement, but element graph was null : " "CollectionReference did not return an expected element graph : " +
+ elementDefinition.getCollectionDefinition().getCollectionPersister().getRole() elementDefinition.getCollectionDefinition().getCollectionPersister().getRole()
); );
} }
@ -407,8 +452,8 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
else { else {
if ( elementGraph != null ) { if ( elementGraph != null ) {
throw new IllegalStateException( throw new IllegalStateException(
"Not expecting CollectionFetchableElement, but element graph was non-null : " "CollectionReference returned an unexpected element graph : " +
+ elementDefinition.getCollectionDefinition().getCollectionPersister().getRole() elementDefinition.getCollectionDefinition().getCollectionPersister().getRole()
); );
} }
} }
@ -416,41 +461,31 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
@Override @Override
public void finishingCollectionElements(CollectionElementDefinition elementDefinition) { public void finishingCollectionElements(CollectionElementDefinition elementDefinition) {
// nothing to do here final Type elementType = elementDefinition.getType();
// - the element graph pushed while starting would be popped in finishing/Entity/finishingComposite if ( elementType.isComponentType() ) {
} // pop it from the stack
@Override
public void startingCompositeCollectionElement(CompositeCollectionElementDefinition compositeElementDefinition) {
log.tracef(
"%s Starting composite collection element for (%s)",
StringHelper.repeat( ">>", fetchSourceStack.size() ),
compositeElementDefinition.getCollectionDefinition().getCollectionPersister().getRole()
);
}
@Override
public void finishingCompositeCollectionElement(CompositeCollectionElementDefinition compositeElementDefinition) {
// pop the current fetch owner, and make sure what we just popped represents this composition
final ExpandingFetchSource popped = popFromStack(); final ExpandingFetchSource popped = popFromStack();
// validation
if ( ! CollectionFetchableElement.class.isInstance( popped ) ) { if ( ! CollectionFetchableElement.class.isInstance( popped ) ) {
throw new WalkingException( "Mismatched FetchSource from stack on pop" ); throw new WalkingException( "Mismatched FetchSource from stack on pop" );
} }
}
// NOTE : not much else we can really check here atm since on the walking spi side we do not have path // entity indexes would be popped during finishingEntity processing
log.tracef( log.tracef(
"%s Finished composite element for : %s", "%s Finished collection element graph : %s",
StringHelper.repeat( "<<", fetchSourceStack.size() ), StringHelper.repeat( "<<", fetchSourceStack.size() ),
compositeElementDefinition.getCollectionDefinition().getCollectionPersister().getRole() elementDefinition.getCollectionDefinition().getCollectionPersister().getRole()
); );
} }
@Override @Override
public void startingComposite(CompositionDefinition compositionDefinition) { public void startingComposite(CompositionDefinition compositionDefinition) {
log.tracef( log.tracef(
"%s Starting composition : %s", "%s Starting composite : %s",
StringHelper.repeat( ">>", fetchSourceStack.size() ), StringHelper.repeat( ">>", fetchSourceStack.size() ),
compositionDefinition.getName() compositionDefinition.getName()
); );
@ -458,6 +493,9 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
if ( fetchSourceStack.isEmpty() ) { if ( fetchSourceStack.isEmpty() ) {
throw new HibernateException( "A component cannot be the root of a walk nor a graph" ); throw new HibernateException( "A component cannot be the root of a walk nor a graph" );
} }
final CompositeFetch compositeFetch = currentSource().buildCompositeFetch( compositionDefinition, this );
pushToStack( (ExpandingFetchSource) compositeFetch );
} }
@Override @Override
@ -469,10 +507,8 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
throw new WalkingException( "Mismatched FetchSource from stack on pop" ); throw new WalkingException( "Mismatched FetchSource from stack on pop" );
} }
// NOTE : not much else we can really check here atm since on the walking spi side we do not have path
log.tracef( log.tracef(
"%s Finished composition : %s", "%s Finishing composite : %s",
StringHelper.repeat( "<<", fetchSourceStack.size() ), StringHelper.repeat( "<<", fetchSourceStack.size() ),
compositionDefinition.getName() compositionDefinition.getName()
); );
@ -672,9 +708,9 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
} }
protected boolean handleCompositeAttribute(CompositionDefinition attributeDefinition) { protected boolean handleCompositeAttribute(CompositionDefinition attributeDefinition) {
final ExpandingFetchSource currentSource = currentSource(); // final ExpandingFetchSource currentSource = currentSource();
final CompositeFetch fetch = currentSource.buildCompositeFetch( attributeDefinition, this ); // final CompositeFetch fetch = currentSource.buildCompositeFetch( attributeDefinition, this );
pushToStack( (ExpandingFetchSource) fetch ); // pushToStack( (ExpandingFetchSource) fetch );
return true; return true;
} }

View File

@ -272,7 +272,10 @@ public class LoadQueryJoinAndFetchProcessor {
// //
// long story short, for now we'll use an assumption that the last join in the CollectionQuerySpace is the // long story short, for now we'll use an assumption that the last join in the CollectionQuerySpace is the
// element join (that's how the joins are built as of now..) // element join (that's how the joins are built as of now..)
// todo : remove this assumption ^^ //
// todo : remove this assumption ^^; maybe we make CollectionQuerySpace "special" and rather than have it
// hold a list of joins, we have it expose the 2 (index, element) separately.
Join collectionElementJoin = null; Join collectionElementJoin = null;
for ( Join collectionJoin : rightHandSide.getJoins() ) { for ( Join collectionJoin : rightHandSide.getJoins() ) {
collectionElementJoin = collectionJoin; collectionElementJoin = collectionJoin;

View File

@ -49,7 +49,7 @@ public interface AssociationVisitationStrategy {
/** /**
* Notification we are starting to walk an entity. * Notification we are starting to walk an entity.
* *
* @param entityDefinition The entity we are starting to walk * @param entityDefinition The entity we are preparing to walk
*/ */
public void startingEntity(EntityDefinition entityDefinition); public void startingEntity(EntityDefinition entityDefinition);
@ -63,7 +63,7 @@ public interface AssociationVisitationStrategy {
/** /**
* Notification we are starting to walk the identifier of an entity. * Notification we are starting to walk the identifier of an entity.
* *
* @param entityIdentifierDefinition The identifier we are starting to walk * @param entityIdentifierDefinition The identifier we are preparing to walk
*/ */
public void startingEntityIdentifier(EntityIdentifierDefinition entityIdentifierDefinition); public void startingEntityIdentifier(EntityIdentifierDefinition entityIdentifierDefinition);
@ -74,22 +74,93 @@ public interface AssociationVisitationStrategy {
*/ */
public void finishingEntityIdentifier(EntityIdentifierDefinition entityIdentifierDefinition); public void finishingEntityIdentifier(EntityIdentifierDefinition entityIdentifierDefinition);
/**
* Notification that we are starting to walk a collection
*
* @param collectionDefinition The collection we are preparing to walk
*/
public void startingCollection(CollectionDefinition collectionDefinition); public void startingCollection(CollectionDefinition collectionDefinition);
/**
* Notification that we are finishing walking a collection
*
* @param collectionDefinition The collection we are finishing
*/
public void finishingCollection(CollectionDefinition collectionDefinition); public void finishingCollection(CollectionDefinition collectionDefinition);
/**
* Notification that we are starting to walk the index of a collection (List/Map). In the case of a Map,
* if the indices (the keys) are entities this will be followed up by a call to {@link #startingEntity}
*
* @param collectionIndexDefinition The collection index we are preparing to walk.
*/
public void startingCollectionIndex(CollectionIndexDefinition collectionIndexDefinition); public void startingCollectionIndex(CollectionIndexDefinition collectionIndexDefinition);
/**
* Notification that we are finishing walking the index of a collection (List/Map).
*
* @param collectionIndexDefinition The collection index we are finishing
*/
public void finishingCollectionIndex(CollectionIndexDefinition collectionIndexDefinition); public void finishingCollectionIndex(CollectionIndexDefinition collectionIndexDefinition);
/**
* Notification that we are starting to look at the element definition for the collection. If the collection
* elements are entities this will be followed up by a call to {@link #startingEntity}
*
* @param elementDefinition The collection element we are preparing to walk..
*/
public void startingCollectionElements(CollectionElementDefinition elementDefinition); public void startingCollectionElements(CollectionElementDefinition elementDefinition);
/**
* Notification that we are finishing walking the elements of a collection (List/Map).
*
* @param elementDefinition The collection element we are finishing
*/
public void finishingCollectionElements(CollectionElementDefinition elementDefinition); public void finishingCollectionElements(CollectionElementDefinition elementDefinition);
/**
* Notification that we are preparing to walk a composite. This is called only for:<ul>
* <li>
* top-level composites for entity attributes. composite entity identifiers do not route through here, see
* {@link #startingEntityIdentifier} if you need to hook into walking the top-level cid composite.
* </li>
* <li>
* All forms of nested composite paths
* </li>
* </ul>
*
* @param compositionDefinition The composite we are preparing to walk.
*/
public void startingComposite(CompositionDefinition compositionDefinition); public void startingComposite(CompositionDefinition compositionDefinition);
/**
* Notification that we are done walking a composite. Called on the back-end of the situations listed
* on {@link #startingComposite}
*
* @param compositionDefinition The composite we are finishing
*/
public void finishingComposite(CompositionDefinition compositionDefinition); public void finishingComposite(CompositionDefinition compositionDefinition);
public void startingCompositeCollectionElement(CompositeCollectionElementDefinition compositionElementDefinition); // get rid of these ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public void finishingCompositeCollectionElement(CompositeCollectionElementDefinition compositionElementDefinition); // public void startingCompositeCollectionElement(CompositeCollectionElementDefinition compositionElementDefinition);
// public void finishingCompositeCollectionElement(CompositeCollectionElementDefinition compositionElementDefinition);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* Notification that we are preparing to walk an attribute. May be followed by calls to {@link #startingEntity}
* (one-to-one, many-to-one), {@link #startingComposite}, or {@link #startingCollection}.
*
* @param attributeDefinition The attribute we are preparing to walk.
*
* @return {@code true} if the walking should continue; {@code false} if walking should stop.
*/
public boolean startingAttribute(AttributeDefinition attributeDefinition); public boolean startingAttribute(AttributeDefinition attributeDefinition);
/**
* Notification that we are finishing walking an attribute.
*
* @param attributeDefinition The attribute we are done walking
*/
public void finishingAttribute(AttributeDefinition attributeDefinition); public void finishingAttribute(AttributeDefinition attributeDefinition);
public void foundAny(AssociationAttributeDefinition attributeDefinition, AnyMappingDefinition anyDefinition); public void foundAny(AssociationAttributeDefinition attributeDefinition, AnyMappingDefinition anyDefinition);

View File

@ -118,6 +118,8 @@ public class MetamodelGraphWalker {
// to make encapsulated and non-encapsulated composite identifiers work the same here, we "cheat" here a // to make encapsulated and non-encapsulated composite identifiers work the same here, we "cheat" here a
// little bit and simply walk the attributes of the composite id in both cases. // little bit and simply walk the attributes of the composite id in both cases.
// this works because the LoadPlans already build the top-level composite for composite ids
if ( identifierDefinition.isEncapsulated() ) { if ( identifierDefinition.isEncapsulated() ) {
// in the encapsulated composite id case that means we have a little bit of duplication between here and // in the encapsulated composite id case that means we have a little bit of duplication between here and
// visitCompositeDefinition, but in the spirit of consistently handling composite ids, that is much better // visitCompositeDefinition, but in the spirit of consistently handling composite ids, that is much better
@ -125,12 +127,12 @@ public class MetamodelGraphWalker {
final EncapsulatedEntityIdentifierDefinition idAsEncapsulated = (EncapsulatedEntityIdentifierDefinition) identifierDefinition; final EncapsulatedEntityIdentifierDefinition idAsEncapsulated = (EncapsulatedEntityIdentifierDefinition) identifierDefinition;
final AttributeDefinition idAttr = idAsEncapsulated.getAttributeDefinition(); final AttributeDefinition idAttr = idAsEncapsulated.getAttributeDefinition();
if ( CompositionDefinition.class.isInstance( idAttr ) ) { if ( CompositionDefinition.class.isInstance( idAttr ) ) {
visitCompositeDefinition( (CompositionDefinition) idAttr ); visitAttributes( (CompositionDefinition) idAttr );
} }
} }
else { else {
// NonEncapsulatedEntityIdentifierDefinition itself is defined as a CompositionDefinition // NonEncapsulatedEntityIdentifierDefinition itself is defined as a CompositionDefinition
visitCompositeDefinition( (NonEncapsulatedEntityIdentifierDefinition) identifierDefinition ); visitAttributes( (NonEncapsulatedEntityIdentifierDefinition) identifierDefinition );
} }
strategy.finishingEntityIdentifier( identifierDefinition ); strategy.finishingEntityIdentifier( identifierDefinition );
@ -252,7 +254,7 @@ public class MetamodelGraphWalker {
strategy.startingCollectionElements( elementDefinition ); strategy.startingCollectionElements( elementDefinition );
if ( elementDefinition.getType().isComponentType() ) { if ( elementDefinition.getType().isComponentType() ) {
visitCompositeCollectionElementDefinition( elementDefinition.toCompositeElementDefinition() ); visitAttributes( elementDefinition.toCompositeElementDefinition() );
} }
else if ( elementDefinition.getType().isEntityType() ) { else if ( elementDefinition.getType().isEntityType() ) {
visitEntityDefinition( elementDefinition.toEntityDefinition() ); visitEntityDefinition( elementDefinition.toEntityDefinition() );
@ -261,14 +263,6 @@ public class MetamodelGraphWalker {
strategy.finishingCollectionElements( elementDefinition ); strategy.finishingCollectionElements( elementDefinition );
} }
private void visitCompositeCollectionElementDefinition(CompositeCollectionElementDefinition compositionElementDefinition) {
strategy.startingCompositeCollectionElement( compositionElementDefinition );
visitAttributes( compositionElementDefinition );
strategy.finishingCompositeCollectionElement( compositionElementDefinition );
}
private final Set<AssociationKey> visitedAssociationKeys = new HashSet<AssociationKey>(); private final Set<AssociationKey> visitedAssociationKeys = new HashSet<AssociationKey>();
/** /**

View File

@ -64,11 +64,16 @@ public class LoadPlanStructureAssertionTest extends BaseUnitTestCase {
cfg.addResource( "org/hibernate/test/onetoone/joined/Person.hbm.xml" ); cfg.addResource( "org/hibernate/test/onetoone/joined/Person.hbm.xml" );
SessionFactoryImplementor sf = (SessionFactoryImplementor) cfg.buildSessionFactory(); SessionFactoryImplementor sf = (SessionFactoryImplementor) cfg.buildSessionFactory();
try {
// doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( org.hibernate.test.onetoone.joined.Person.class ) ); // doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( org.hibernate.test.onetoone.joined.Person.class ) );
doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( org.hibernate.test.onetoone.joined.Entity.class ) ); doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( org.hibernate.test.onetoone.joined.Entity.class ) );
// doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( org.hibernate.test.onetoone.joined.Address.class ) ); // doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( org.hibernate.test.onetoone.joined.Address.class ) );
} }
finally {
sf.close();
}
}
@Test @Test
public void testSpecialOneToOne() { public void testSpecialOneToOne() {
@ -77,8 +82,13 @@ public class LoadPlanStructureAssertionTest extends BaseUnitTestCase {
cfg.addResource( "org/hibernate/test/onetoone/formula/Person.hbm.xml" ); cfg.addResource( "org/hibernate/test/onetoone/formula/Person.hbm.xml" );
SessionFactoryImplementor sf = (SessionFactoryImplementor) cfg.buildSessionFactory(); SessionFactoryImplementor sf = (SessionFactoryImplementor) cfg.buildSessionFactory();
try {
doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( org.hibernate.test.onetoone.formula.Person.class ) ); doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( org.hibernate.test.onetoone.formula.Person.class ) );
} }
finally {
sf.close();
}
}
@Test @Test
public void testEncapsulatedCompositeIdNoFetches1() { public void testEncapsulatedCompositeIdNoFetches1() {
@ -88,9 +98,15 @@ public class LoadPlanStructureAssertionTest extends BaseUnitTestCase {
cfg.addAnnotatedClass( EncapsulatedCompositeIdResultSetProcessorTest.CardField.class ); cfg.addAnnotatedClass( EncapsulatedCompositeIdResultSetProcessorTest.CardField.class );
cfg.addAnnotatedClass( EncapsulatedCompositeIdResultSetProcessorTest.Card.class ); cfg.addAnnotatedClass( EncapsulatedCompositeIdResultSetProcessorTest.Card.class );
SessionFactoryImplementor sf = (SessionFactoryImplementor) cfg.buildSessionFactory(); SessionFactoryImplementor sf = (SessionFactoryImplementor) cfg.buildSessionFactory();
try {
doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( EncapsulatedCompositeIdResultSetProcessorTest.CardField.class ) ); doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( EncapsulatedCompositeIdResultSetProcessorTest.CardField.class ) );
doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( EncapsulatedCompositeIdResultSetProcessorTest.Card.class ) ); doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( EncapsulatedCompositeIdResultSetProcessorTest.Card.class ) );
} }
finally {
sf.close();
}
}
@Test @Test
public void testEncapsulatedCompositeIdNoFetches2() { public void testEncapsulatedCompositeIdNoFetches2() {
@ -99,8 +115,14 @@ public class LoadPlanStructureAssertionTest extends BaseUnitTestCase {
Configuration cfg = new Configuration(); Configuration cfg = new Configuration();
cfg.addAnnotatedClass( EncapsulatedCompositeIdResultSetProcessorTest.Parent.class ); cfg.addAnnotatedClass( EncapsulatedCompositeIdResultSetProcessorTest.Parent.class );
SessionFactoryImplementor sf = (SessionFactoryImplementor) cfg.buildSessionFactory(); SessionFactoryImplementor sf = (SessionFactoryImplementor) cfg.buildSessionFactory();
try {
doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( EncapsulatedCompositeIdResultSetProcessorTest.Parent.class ) ); doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( EncapsulatedCompositeIdResultSetProcessorTest.Parent.class ) );
} }
finally {
sf.close();
}
}
@Test @Test
public void testEncapsulatedCompositeIdWithFetches1() { public void testEncapsulatedCompositeIdWithFetches1() {
@ -112,6 +134,7 @@ public class LoadPlanStructureAssertionTest extends BaseUnitTestCase {
SessionFactoryImplementor sf = (SessionFactoryImplementor) cfg.buildSessionFactory(); SessionFactoryImplementor sf = (SessionFactoryImplementor) cfg.buildSessionFactory();
try {
final OuterJoinLoadable cardFieldPersister = (OuterJoinLoadable) sf.getClassMetadata( CardField.class ); final OuterJoinLoadable cardFieldPersister = (OuterJoinLoadable) sf.getClassMetadata( CardField.class );
doCompare( sf, cardFieldPersister ); doCompare( sf, cardFieldPersister );
@ -155,6 +178,10 @@ public class LoadPlanStructureAssertionTest extends BaseUnitTestCase {
// a special "identifier reader". generated aliases could help here too to remove cyclic-ness from the graph. // a special "identifier reader". generated aliases could help here too to remove cyclic-ness from the graph.
// but at any rate, we need to know still when this becomes circularity // but at any rate, we need to know still when this becomes circularity
} }
finally {
sf.close();
}
}
@Test @Test
public void testEncapsulatedCompositeIdWithFetches2() { public void testEncapsulatedCompositeIdWithFetches2() {
@ -165,6 +192,8 @@ public class LoadPlanStructureAssertionTest extends BaseUnitTestCase {
cfg.addAnnotatedClass( PrimaryKey.class ); cfg.addAnnotatedClass( PrimaryKey.class );
final SessionFactoryImplementor sf = (SessionFactoryImplementor) cfg.buildSessionFactory(); final SessionFactoryImplementor sf = (SessionFactoryImplementor) cfg.buildSessionFactory();
try {
final OuterJoinLoadable cardPersister = (OuterJoinLoadable) sf.getClassMetadata( Card.class ); final OuterJoinLoadable cardPersister = (OuterJoinLoadable) sf.getClassMetadata( Card.class );
doCompare( sf, cardPersister ); doCompare( sf, cardPersister );
@ -206,13 +235,23 @@ public class LoadPlanStructureAssertionTest extends BaseUnitTestCase {
); );
assertEquals( Key.class.getName(), keyFetch.getEntityPersister().getEntityName() ); assertEquals( Key.class.getName(), keyFetch.getEntityPersister().getEntityName() );
} }
finally {
sf.close();
}
}
@Test @Test
public void testManyToMany() { public void testManyToMany() {
Configuration cfg = new Configuration(); Configuration cfg = new Configuration();
cfg.addResource( "org/hibernate/test/immutable/entitywithmutablecollection/inverse/ContractVariation.hbm.xml" ); cfg.addResource( "org/hibernate/test/immutable/entitywithmutablecollection/inverse/ContractVariation.hbm.xml" );
SessionFactoryImplementor sf = (SessionFactoryImplementor) cfg.buildSessionFactory(); SessionFactoryImplementor sf = (SessionFactoryImplementor) cfg.buildSessionFactory();
try {
doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( org.hibernate.test.immutable.entitywithmutablecollection.Contract.class ) ); doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( org.hibernate.test.immutable.entitywithmutablecollection.Contract.class ) );
}
finally {
sf.close();
}
} }

View File

@ -45,8 +45,12 @@ public class CompositesWalkingTest extends BaseUnitTestCase {
final SessionFactory sf = new Configuration() final SessionFactory sf = new Configuration()
.addAnnotatedClass( TestCourse.class ) .addAnnotatedClass( TestCourse.class )
.buildSessionFactory(); .buildSessionFactory();
try {
final EntityPersister ep = (EntityPersister) sf.getClassMetadata( TestCourse.class ); final EntityPersister ep = (EntityPersister) sf.getClassMetadata( TestCourse.class );
MetamodelGraphWalker.visitEntity( new LoggingAssociationVisitationStrategy(), ep ); MetamodelGraphWalker.visitEntity( new LoggingAssociationVisitationStrategy(), ep );
} }
finally {
sf.close();
}
}
} }

View File

@ -131,7 +131,7 @@ public class LoggingAssociationVisitationStrategy implements AssociationVisitati
System.out.println( System.out.println(
String.format( String.format(
"%s Finishing composite (%s)", "%s Finishing composite (%s)",
StringHelper.repeat( ">>", depth-- ), StringHelper.repeat( "<<", depth-- ),
compositionDefinition.getName() compositionDefinition.getName()
) )
); );
@ -206,28 +206,28 @@ public class LoggingAssociationVisitationStrategy implements AssociationVisitati
// why do we have these + startingCollectionElements/finishingCollectionElements ??? // why do we have these + startingCollectionElements/finishingCollectionElements ???
//
@Override // @Override
public void startingCompositeCollectionElement(CompositeCollectionElementDefinition compositionElementDefinition) { // public void startingCompositeCollectionElement(CompositeCollectionElementDefinition compositionElementDefinition) {
System.out.println( // System.out.println(
String.format( // String.format(
"%s Starting composite (%s)", // "%s Starting composite (%s)",
StringHelper.repeat( ">>", ++depth ), // StringHelper.repeat( ">>", ++depth ),
compositionElementDefinition.getCollectionDefinition().getCollectionPersister().getRole() // compositionElementDefinition.getCollectionDefinition().getCollectionPersister().getRole()
) // )
); // );
} // }
//
@Override // @Override
public void finishingCompositeCollectionElement(CompositeCollectionElementDefinition compositionElementDefinition) { // public void finishingCompositeCollectionElement(CompositeCollectionElementDefinition compositionElementDefinition) {
System.out.println( // System.out.println(
String.format( // String.format(
"%s Finishing composite (%s)", // "%s Finishing composite (%s)",
StringHelper.repeat( "<<", depth-- ), // StringHelper.repeat( "<<", depth-- ),
compositionElementDefinition.getCollectionDefinition().getCollectionPersister().getRole() // compositionElementDefinition.getCollectionDefinition().getCollectionPersister().getRole()
) // )
); // );
} // }
@Override @Override
public void foundAny(AssociationAttributeDefinition attributeDefinition, AnyMappingDefinition anyDefinition) { public void foundAny(AssociationAttributeDefinition attributeDefinition, AnyMappingDefinition anyDefinition) {

View File

@ -0,0 +1,49 @@
/*
* 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.test.loadplans.walking;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.walking.spi.MetamodelGraphWalker;
import org.junit.Test;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.hibernate.test.loadplans.process.EncapsulatedCompositeAttributeResultSetProcessorTest.Person;
import org.hibernate.test.loadplans.process.EncapsulatedCompositeAttributeResultSetProcessorTest.Customer;
/**
* @author Steve Ebersole
*/
public class NestedCompositeElementTest extends BaseCoreFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] { Person.class, Customer.class };
}
@Test
public void testWalkingKeyManyToOneGraphs() {
final EntityPersister ep = (EntityPersister) sessionFactory().getClassMetadata( Customer.class );
MetamodelGraphWalker.visitEntity( new LoggingAssociationVisitationStrategy(), ep );
}
}