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: {
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
}
@Override
public void startingCompositeCollectionElement(CompositeCollectionElementDefinition compositeElementDefinition) {
log.tracef(
"%s Starting composite collection element for (%s)",
StringHelper.repeat( ">>", fetchOwnerStack.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 FetchOwner poppedFetchOwner = popFromStack();
if ( ! CompositeElementGraph.class.isInstance( poppedFetchOwner ) ) {
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
log.tracef(
"%s Finished composite element for : %s",
StringHelper.repeat( "<<", fetchOwnerStack.size() ),
compositeElementDefinition.getCollectionDefinition().getCollectionPersister().getRole()
);
}
// @Override
// public void startingCompositeCollectionElement(CompositeCollectionElementDefinition compositeElementDefinition) {
// log.tracef(
// "%s Starting composite collection element for (%s)",
// StringHelper.repeat( ">>", fetchOwnerStack.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 FetchOwner poppedFetchOwner = popFromStack();
//
// if ( ! CompositeElementGraph.class.isInstance( poppedFetchOwner ) ) {
// 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
//
// log.tracef(
// "%s Finished composite element for : %s",
// StringHelper.repeat( "<<", fetchOwnerStack.size() ),
// compositeElementDefinition.getCollectionDefinition().getCollectionPersister().getRole()
// );
// }
@Override
public void finishingCollection(CollectionDefinition collectionDefinition) {

View File

@ -39,21 +39,14 @@ public abstract class AbstractCompositeEntityIdentifierDescription
implements EntityIdentifierDescription, FetchSource, ExpandingEntityIdentifierDescription {
private final EntityReference entityReference;
private final CompositeQuerySpace compositeQuerySpace;
protected AbstractCompositeEntityIdentifierDescription(
EntityReference entityReference,
CompositeQuerySpace compositeQuerySpace,
CompositeType identifierType,
PropertyPath propertyPath) {
super( identifierType, propertyPath );
super( identifierType, compositeQuerySpace, false, propertyPath );
this.entityReference = entityReference;
this.compositeQuerySpace = compositeQuerySpace;
}
@Override
protected String getFetchLeftHandSideUid() {
return compositeQuerySpace.getUid();
}
@Override
@ -66,11 +59,4 @@ public abstract class AbstractCompositeEntityIdentifierDescription
// the source for this (as a Fetch) is the entity reference
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.spi.CollectionFetch;
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.Fetch;
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 final CompositeType compositeType;
private final CompositeQuerySpace compositeQuerySpace;
private final PropertyPath propertyPath;
private final boolean allowCollectionFetches;
private List<Fetch> fetches;
protected AbstractCompositeFetch(CompositeType compositeType, PropertyPath propertyPath) {
protected AbstractCompositeFetch(
CompositeType compositeType,
CompositeQuerySpace compositeQuerySpace,
boolean allowCollectionFetches, PropertyPath propertyPath) {
this.compositeType = compositeType;
this.compositeQuerySpace = compositeQuerySpace;
this.allowCollectionFetches = allowCollectionFetches;
this.propertyPath = propertyPath;
}
protected abstract String getFetchLeftHandSideUid();
@SuppressWarnings("UnusedParameters")
protected CompositeQuerySpace resolveCompositeQuerySpace(LoadPlanBuildingContext loadPlanBuildingContext) {
return compositeQuerySpace;
}
@Override
public String getQuerySpaceUid() {
return compositeQuerySpace.getUid();
}
@Override
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(
getFetchLeftHandSideUid()
final ExpandingQuerySpace leftHandSide = (ExpandingQuerySpace) resolveCompositeQuerySpace(
loadPlanBuildingContext
);
final Join join = leftHandSide.addEntityJoin(
attributeDefinition,
@ -122,11 +138,18 @@ public abstract class AbstractCompositeFetch implements CompositeFetch, Expandin
public CompositeFetch buildCompositeFetch(
CompositionDefinition attributeDefinition,
LoadPlanBuildingContext loadPlanBuildingContext) {
final ExpandingQuerySpace leftHandSide = (ExpandingQuerySpace) resolveCompositeQuerySpace( loadPlanBuildingContext );
final Join join = leftHandSide.addCompositeJoin(
attributeDefinition,
loadPlanBuildingContext.getQuerySpaces().generateImplicitUid()
);
final NestedCompositeFetchImpl fetch = new NestedCompositeFetchImpl(
this,
attributeDefinition.getType(),
getPropertyPath(),
getFetchLeftHandSideUid()
(CompositeQuerySpace) join.getRightHandSide(),
allowCollectionFetches,
getPropertyPath()
);
addFetch( fetch );
return fetch;
@ -137,6 +160,15 @@ public abstract class AbstractCompositeFetch implements CompositeFetch, Expandin
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy,
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,
// 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) {
this.entityQuerySpace = entityQuerySpace;
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,
* Long, etc) or some form of composite id (either encapsulated or not).
*
* @param querySpace The entity query space
*
* @return the descriptor for the identifier
*/
private EntityIdentifierDescription buildIdentifierDescription(EntityQuerySpace querySpace) {
private EntityIdentifierDescription buildIdentifierDescription() {
final EntityPersister persister = entityQuerySpace.getEntityPersister();
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(
attributeDefinition,
fetchedPersister,
@ -196,9 +193,17 @@ public abstract class AbstractEntityReference implements EntityReference, Expand
public CompositeFetch buildCompositeFetch(
CompositionDefinition attributeDefinition,
LoadPlanBuildingContext loadPlanBuildingContext) {
final ExpandingQuerySpace leftHandSide = (ExpandingQuerySpace) entityQuerySpace;
final Join join = leftHandSide.addCompositeJoin(
attributeDefinition,
loadPlanBuildingContext.getQuerySpaces().generateImplicitUid()
);
final CompositeFetchImpl fetch = new CompositeFetchImpl(
this,
attributeDefinition.getType(),
(CompositeQuerySpace) join.getRightHandSide(),
true,
getPropertyPath()
);
addFetch( fetch );

View File

@ -23,19 +23,17 @@
*/
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.CollectionReference;
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.Join;
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
import org.hibernate.persister.walking.spi.WalkingException;
import org.hibernate.type.CompositeType;
/**
* Models the element graph of a collection, where the elements are composite
*
* @author Steve Ebersole
*/
public class CollectionFetchableElementCompositeGraph
@ -43,23 +41,16 @@ public class CollectionFetchableElementCompositeGraph
implements CompositeFetch, CollectionFetchableElement {
private final CollectionReference collectionReference;
private final Join compositeJoin;
public CollectionFetchableElementCompositeGraph(
CollectionReference collectionReference,
Join compositeJoin) {
public CollectionFetchableElementCompositeGraph(CollectionReference collectionReference, Join compositeJoin) {
super(
(CompositeType) compositeJoin.getRightHandSide().getPropertyMapping().getType(),
(CompositeQuerySpace) compositeJoin.getRightHandSide(),
false,
// these property paths are just informational...
collectionReference.getPropertyPath().append( "<element>" )
);
this.collectionReference = collectionReference;
this.compositeJoin = compositeJoin;
}
@Override
protected String getFetchLeftHandSideUid() {
return compositeJoin.getRightHandSide().getUid();
}
@Override
@ -71,17 +62,4 @@ public class CollectionFetchableElementCompositeGraph
public FetchSource getSource() {
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;
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.CollectionReference;
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.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.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
*/
public class CollectionFetchableIndexCompositeGraph
@ -45,17 +43,17 @@ public class CollectionFetchableIndexCompositeGraph
implements CompositeFetch, CollectionFetchableIndex {
private final CollectionReference collectionReference;
private final Join compositeJoin;
public CollectionFetchableIndexCompositeGraph(
CollectionReference collectionReference,
Join compositeJoin) {
super(
extractIndexType( compositeJoin ),
(CompositeQuerySpace) compositeJoin.getRightHandSide(),
false,
collectionReference.getPropertyPath().append( "<index>" )
);
this.collectionReference = collectionReference;
this.compositeJoin = compositeJoin;
}
private static CompositeType extractIndexType(Join compositeJoin) {
@ -67,12 +65,6 @@ public class CollectionFetchableIndexCompositeGraph
throw new IllegalArgumentException( "Could note extract collection composite-index" );
}
@Override
protected String getFetchLeftHandSideUid() {
return compositeJoin.getRightHandSide().getUid();
}
@Override
public CollectionReference getCollectionReference() {
return collectionReference;
@ -82,24 +74,4 @@ public class CollectionFetchableIndexCompositeGraph
public FetchSource getSource() {
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.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.type.CompositeType;
@ -33,28 +33,20 @@ import org.hibernate.type.CompositeType;
* @author Steve Ebersole
*/
public class CompositeFetchImpl extends AbstractCompositeFetch implements CompositeFetch {
private final EntityReference source;
private final FetchSource source;
protected CompositeFetchImpl(
EntityReference source,
FetchSource source,
CompositeType compositeType,
CompositeQuerySpace compositeQuerySpace,
boolean allowCollectionFetches,
PropertyPath propertyPath) {
super( compositeType, propertyPath );
super( compositeType, compositeQuerySpace, allowCollectionFetches, propertyPath );
this.source = source;
}
@Override
protected String getFetchLeftHandSideUid() {
return getSource().getQuerySpaceUid();
}
@Override
public FetchSource getSource() {
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;
/**
* 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
*/
public class EncapsulatedEntityIdentifierDescription
extends AbstractCompositeEntityIdentifierDescription
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(
EntityReference entityReference,
CompositeQuerySpace compositeQuerySpace,
CompositeType identifierType, PropertyPath propertyPath) {
super( entityReference, compositeQuerySpace, identifierType, propertyPath );
CompositeType compositeType,
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.plan2.spi.CompositeFetch;
import org.hibernate.loader.plan2.spi.CompositeQuerySpace;
import org.hibernate.loader.plan2.spi.FetchSource;
import org.hibernate.type.CompositeType;
@ -33,30 +34,18 @@ import org.hibernate.type.CompositeType;
*/
public class NestedCompositeFetchImpl extends AbstractCompositeFetch {
private final CompositeFetch source;
private final String fetchLeftHandSideUid;
public NestedCompositeFetchImpl(
CompositeFetch source,
CompositeType type,
PropertyPath propertyPath,
String fetchLeftHandSideUid) {
super( type, propertyPath );
CompositeQuerySpace compositeQuerySpace,
boolean allowCollectionFetches, PropertyPath propertyPath) {
super( type, compositeQuerySpace, allowCollectionFetches, propertyPath );
this.source = source;
this.fetchLeftHandSideUid = fetchLeftHandSideUid;
}
@Override
protected String getFetchLeftHandSideUid() {
return fetchLeftHandSideUid;
}
@Override
public FetchSource getSource() {
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;
/**
* 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
*/
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(
EntityReference entityReference,
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.CollectionElementDefinition;
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.EntityDefinition;
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
@ -201,7 +200,13 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
final ExpandingFetchSource fetchSource = popFromStack();
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;
@ -366,39 +371,79 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
}
@Override
public void startingCollectionIndex(CollectionIndexDefinition collectionIndexDefinition) {
final Type indexType = collectionIndexDefinition.getType();
if ( indexType.isAssociationType() || indexType.isComponentType() ) {
final CollectionReference collectionReference = collectionReferenceStack.peekFirst();
final CollectionFetchableIndex indexGraph = collectionReference.getIndexGraph();
public void startingCollectionIndex(CollectionIndexDefinition indexDefinition) {
final Type indexType = indexDefinition.getType();
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 CollectionFetchableIndex indexGraph = collectionReference.getIndexGraph();
if ( indexType.isEntityType() || indexType.isComponentType() ) {
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 );
}
else {
if ( indexGraph != null ) {
throw new WalkingException(
"CollectionReference returned an unexpected index graph : " +
indexDefinition.getCollectionDefinition().getCollectionPersister().getRole()
);
}
}
}
@Override
public void finishingCollectionIndex(CollectionIndexDefinition collectionIndexDefinition) {
// nothing to do here
// - the element graph pushed while starting would be popped in finishingEntity/finishingComposite
public void finishingCollectionIndex(CollectionIndexDefinition indexDefinition) {
final Type indexType = indexDefinition.getType();
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
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 CollectionFetchableElement elementGraph = collectionReference.getElementGraph();
final Type elementType = elementDefinition.getType();
final boolean expectFetchSourceElements =
( elementType.isAssociationType() || elementType.isComponentType() )
&& ! elementType.isAnyType();
if ( expectFetchSourceElements ) {
if ( elementType.isAssociationType() || elementType.isComponentType() ) {
if ( elementGraph == null ) {
throw new IllegalStateException(
"Expecting CollectionFetchableElement, but element graph was null : "
+ elementDefinition.getCollectionDefinition().getCollectionPersister().getRole()
"CollectionReference did not return an expected element graph : " +
elementDefinition.getCollectionDefinition().getCollectionPersister().getRole()
);
}
@ -407,8 +452,8 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
else {
if ( elementGraph != null ) {
throw new IllegalStateException(
"Not expecting CollectionFetchableElement, but element graph was non-null : "
+ elementDefinition.getCollectionDefinition().getCollectionPersister().getRole()
"CollectionReference returned an unexpected element graph : " +
elementDefinition.getCollectionDefinition().getCollectionPersister().getRole()
);
}
}
@ -416,41 +461,31 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
@Override
public void finishingCollectionElements(CollectionElementDefinition elementDefinition) {
// nothing to do here
// - the element graph pushed while starting would be popped in finishing/Entity/finishingComposite
}
final Type elementType = elementDefinition.getType();
if ( elementType.isComponentType() ) {
// pop it from the stack
final ExpandingFetchSource popped = popFromStack();
@Override
public void startingCompositeCollectionElement(CompositeCollectionElementDefinition compositeElementDefinition) {
log.tracef(
"%s Starting composite collection element for (%s)",
StringHelper.repeat( ">>", fetchSourceStack.size() ),
compositeElementDefinition.getCollectionDefinition().getCollectionPersister().getRole()
);
}
// validation
@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();
if ( ! CollectionFetchableElement.class.isInstance( popped ) ) {
throw new WalkingException( "Mismatched FetchSource from stack on pop" );
if ( ! CollectionFetchableElement.class.isInstance( popped ) ) {
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(
"%s Finished composite element for : %s",
"%s Finished collection element graph : %s",
StringHelper.repeat( "<<", fetchSourceStack.size() ),
compositeElementDefinition.getCollectionDefinition().getCollectionPersister().getRole()
elementDefinition.getCollectionDefinition().getCollectionPersister().getRole()
);
}
@Override
public void startingComposite(CompositionDefinition compositionDefinition) {
log.tracef(
"%s Starting composition : %s",
"%s Starting composite : %s",
StringHelper.repeat( ">>", fetchSourceStack.size() ),
compositionDefinition.getName()
);
@ -458,6 +493,9 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
if ( fetchSourceStack.isEmpty() ) {
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
@ -469,10 +507,8 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
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(
"%s Finished composition : %s",
"%s Finishing composite : %s",
StringHelper.repeat( "<<", fetchSourceStack.size() ),
compositionDefinition.getName()
);
@ -672,9 +708,9 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
}
protected boolean handleCompositeAttribute(CompositionDefinition attributeDefinition) {
final ExpandingFetchSource currentSource = currentSource();
final CompositeFetch fetch = currentSource.buildCompositeFetch( attributeDefinition, this );
pushToStack( (ExpandingFetchSource) fetch );
// final ExpandingFetchSource currentSource = currentSource();
// final CompositeFetch fetch = currentSource.buildCompositeFetch( attributeDefinition, this );
// pushToStack( (ExpandingFetchSource) fetch );
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
// 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;
for ( Join collectionJoin : rightHandSide.getJoins() ) {
collectionElementJoin = collectionJoin;

View File

@ -49,7 +49,7 @@ public interface AssociationVisitationStrategy {
/**
* 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);
@ -63,7 +63,7 @@ public interface AssociationVisitationStrategy {
/**
* 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);
@ -74,22 +74,93 @@ public interface AssociationVisitationStrategy {
*/
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);
/**
* Notification that we are finishing walking a collection
*
* @param collectionDefinition The collection we are finishing
*/
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);
/**
* 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);
/**
* 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);
/**
* 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);
/**
* 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);
/**
* 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 startingCompositeCollectionElement(CompositeCollectionElementDefinition compositionElementDefinition);
public void finishingCompositeCollectionElement(CompositeCollectionElementDefinition compositionElementDefinition);
// get rid of these ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 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);
/**
* Notification that we are finishing walking an attribute.
*
* @param attributeDefinition The attribute we are done walking
*/
public void finishingAttribute(AttributeDefinition attributeDefinition);
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
// 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() ) {
// 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
@ -125,12 +127,12 @@ public class MetamodelGraphWalker {
final EncapsulatedEntityIdentifierDefinition idAsEncapsulated = (EncapsulatedEntityIdentifierDefinition) identifierDefinition;
final AttributeDefinition idAttr = idAsEncapsulated.getAttributeDefinition();
if ( CompositionDefinition.class.isInstance( idAttr ) ) {
visitCompositeDefinition( (CompositionDefinition) idAttr );
visitAttributes( (CompositionDefinition) idAttr );
}
}
else {
// NonEncapsulatedEntityIdentifierDefinition itself is defined as a CompositionDefinition
visitCompositeDefinition( (NonEncapsulatedEntityIdentifierDefinition) identifierDefinition );
visitAttributes( (NonEncapsulatedEntityIdentifierDefinition) identifierDefinition );
}
strategy.finishingEntityIdentifier( identifierDefinition );
@ -252,7 +254,7 @@ public class MetamodelGraphWalker {
strategy.startingCollectionElements( elementDefinition );
if ( elementDefinition.getType().isComponentType() ) {
visitCompositeCollectionElementDefinition( elementDefinition.toCompositeElementDefinition() );
visitAttributes( elementDefinition.toCompositeElementDefinition() );
}
else if ( elementDefinition.getType().isEntityType() ) {
visitEntityDefinition( elementDefinition.toEntityDefinition() );
@ -261,14 +263,6 @@ public class MetamodelGraphWalker {
strategy.finishingCollectionElements( elementDefinition );
}
private void visitCompositeCollectionElementDefinition(CompositeCollectionElementDefinition compositionElementDefinition) {
strategy.startingCompositeCollectionElement( compositionElementDefinition );
visitAttributes( compositionElementDefinition );
strategy.finishingCompositeCollectionElement( compositionElementDefinition );
}
private final Set<AssociationKey> visitedAssociationKeys = new HashSet<AssociationKey>();
/**

View File

@ -64,10 +64,15 @@ public class LoadPlanStructureAssertionTest extends BaseUnitTestCase {
cfg.addResource( "org/hibernate/test/onetoone/joined/Person.hbm.xml" );
SessionFactoryImplementor sf = (SessionFactoryImplementor) cfg.buildSessionFactory();
// doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( org.hibernate.test.onetoone.joined.Person.class ) );
doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( org.hibernate.test.onetoone.joined.Entity.class ) );
try {
// 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.Address.class ) );
// doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( org.hibernate.test.onetoone.joined.Address.class ) );
}
finally {
sf.close();
}
}
@Test
@ -77,7 +82,12 @@ public class LoadPlanStructureAssertionTest extends BaseUnitTestCase {
cfg.addResource( "org/hibernate/test/onetoone/formula/Person.hbm.xml" );
SessionFactoryImplementor sf = (SessionFactoryImplementor) cfg.buildSessionFactory();
doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( org.hibernate.test.onetoone.formula.Person.class ) );
try {
doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( org.hibernate.test.onetoone.formula.Person.class ) );
}
finally {
sf.close();
}
}
@Test
@ -88,8 +98,14 @@ public class LoadPlanStructureAssertionTest extends BaseUnitTestCase {
cfg.addAnnotatedClass( EncapsulatedCompositeIdResultSetProcessorTest.CardField.class );
cfg.addAnnotatedClass( EncapsulatedCompositeIdResultSetProcessorTest.Card.class );
SessionFactoryImplementor sf = (SessionFactoryImplementor) cfg.buildSessionFactory();
doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( EncapsulatedCompositeIdResultSetProcessorTest.CardField.class ) );
doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( EncapsulatedCompositeIdResultSetProcessorTest.Card.class ) );
try {
doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( EncapsulatedCompositeIdResultSetProcessorTest.CardField.class ) );
doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( EncapsulatedCompositeIdResultSetProcessorTest.Card.class ) );
}
finally {
sf.close();
}
}
@Test
@ -99,7 +115,13 @@ public class LoadPlanStructureAssertionTest extends BaseUnitTestCase {
Configuration cfg = new Configuration();
cfg.addAnnotatedClass( EncapsulatedCompositeIdResultSetProcessorTest.Parent.class );
SessionFactoryImplementor sf = (SessionFactoryImplementor) cfg.buildSessionFactory();
doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( EncapsulatedCompositeIdResultSetProcessorTest.Parent.class ) );
try {
doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( EncapsulatedCompositeIdResultSetProcessorTest.Parent.class ) );
}
finally {
sf.close();
}
}
@Test
@ -112,48 +134,53 @@ public class LoadPlanStructureAssertionTest extends BaseUnitTestCase {
SessionFactoryImplementor sf = (SessionFactoryImplementor) cfg.buildSessionFactory();
final OuterJoinLoadable cardFieldPersister = (OuterJoinLoadable) sf.getClassMetadata( CardField.class );
doCompare( sf, cardFieldPersister );
try {
final OuterJoinLoadable cardFieldPersister = (OuterJoinLoadable) sf.getClassMetadata( CardField.class );
doCompare( sf, cardFieldPersister );
final LoadPlan loadPlan = LoadPlanStructureAssertionHelper.INSTANCE.buildLoadPlan( sf, cardFieldPersister );
assertEquals( LoadPlan.Disposition.ENTITY_LOADER, loadPlan.getDisposition() );
assertEquals( 1, loadPlan.getReturns().size() );
final EntityReturn cardFieldReturn = assertTyping( EntityReturn.class, loadPlan.getReturns().get( 0 ) );
assertEquals( 0, cardFieldReturn.getFetches().length );
final LoadPlan loadPlan = LoadPlanStructureAssertionHelper.INSTANCE.buildLoadPlan( sf, cardFieldPersister );
assertEquals( LoadPlan.Disposition.ENTITY_LOADER, loadPlan.getDisposition() );
assertEquals( 1, loadPlan.getReturns().size() );
final EntityReturn cardFieldReturn = assertTyping( EntityReturn.class, loadPlan.getReturns().get( 0 ) );
assertEquals( 0, cardFieldReturn.getFetches().length );
// CardField defines a composite pk with 2 fetches : Card and Key (the id description acts as the composite)
assertTrue( cardFieldReturn.getIdentifierDescription().hasFetches() );
final FetchSource cardFieldIdAsFetchSource = assertTyping( FetchSource.class, cardFieldReturn.getIdentifierDescription() );
assertEquals( 2, cardFieldIdAsFetchSource.getFetches().length );
// CardField defines a composite pk with 2 fetches : Card and Key (the id description acts as the composite)
assertTrue( cardFieldReturn.getIdentifierDescription().hasFetches() );
final FetchSource cardFieldIdAsFetchSource = assertTyping( FetchSource.class, cardFieldReturn.getIdentifierDescription() );
assertEquals( 2, cardFieldIdAsFetchSource.getFetches().length );
// First the key-many-to-one to Card...
final EntityFetch cardFieldIdCardFetch = assertTyping(
EntityFetch.class,
cardFieldIdAsFetchSource.getFetches()[0]
);
assertFalse( cardFieldIdCardFetch.getIdentifierDescription().hasFetches() );
// i think this one might be a mistake; i think the collection reader still needs to be registered. Its zero
// because the inverse of the key-many-to-one already had a registered AssociationKey and so saw the
// CollectionFetch as a circularity (I think)
assertEquals( 0, cardFieldIdCardFetch.getFetches().length );
// First the key-many-to-one to Card...
final EntityFetch cardFieldIdCardFetch = assertTyping(
EntityFetch.class,
cardFieldIdAsFetchSource.getFetches()[0]
);
assertFalse( cardFieldIdCardFetch.getIdentifierDescription().hasFetches() );
// i think this one might be a mistake; i think the collection reader still needs to be registered. Its zero
// because the inverse of the key-many-to-one already had a registered AssociationKey and so saw the
// CollectionFetch as a circularity (I think)
assertEquals( 0, cardFieldIdCardFetch.getFetches().length );
// then the Key..
final EntityFetch cardFieldIdKeyFetch = assertTyping(
EntityFetch.class,
cardFieldIdAsFetchSource.getFetches()[1]
);
assertFalse( cardFieldIdKeyFetch.getIdentifierDescription().hasFetches() );
assertEquals( 0, cardFieldIdKeyFetch.getFetches().length );
// then the Key..
final EntityFetch cardFieldIdKeyFetch = assertTyping(
EntityFetch.class,
cardFieldIdAsFetchSource.getFetches()[1]
);
assertFalse( cardFieldIdKeyFetch.getIdentifierDescription().hasFetches() );
assertEquals( 0, cardFieldIdKeyFetch.getFetches().length );
// we need the readers ordered in a certain manner. Here specifically: Fetch(Card), Fetch(Key), Return(CardField)
//
// additionally, we need Fetch(Card) and Fetch(Key) to be hydrated/semi-resolved before attempting to
// resolve the EntityKey for Return(CardField)
//
// together those sound like argument enough to continue keeping readers for "identifier fetches" as part of
// 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
// we need the readers ordered in a certain manner. Here specifically: Fetch(Card), Fetch(Key), Return(CardField)
//
// additionally, we need Fetch(Card) and Fetch(Key) to be hydrated/semi-resolved before attempting to
// resolve the EntityKey for Return(CardField)
//
// together those sound like argument enough to continue keeping readers for "identifier fetches" as part of
// 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
}
finally {
sf.close();
}
}
@Test
@ -165,46 +192,52 @@ public class LoadPlanStructureAssertionTest extends BaseUnitTestCase {
cfg.addAnnotatedClass( PrimaryKey.class );
final SessionFactoryImplementor sf = (SessionFactoryImplementor) cfg.buildSessionFactory();
final OuterJoinLoadable cardPersister = (OuterJoinLoadable) sf.getClassMetadata( Card.class );
doCompare( sf, cardPersister );
final LoadPlan cardLoadPlan = LoadPlanStructureAssertionHelper.INSTANCE.buildLoadPlan( sf, cardPersister );
assertEquals( LoadPlan.Disposition.ENTITY_LOADER, cardLoadPlan.getDisposition() );
assertEquals( 1, cardLoadPlan.getReturns().size() );
try {
final OuterJoinLoadable cardPersister = (OuterJoinLoadable) sf.getClassMetadata( Card.class );
doCompare( sf, cardPersister );
// Check the root EntityReturn(Card)
final EntityReturn cardReturn = assertTyping( EntityReturn.class, cardLoadPlan.getReturns().get( 0 ) );
assertFalse( cardReturn.getIdentifierDescription().hasFetches() );
final LoadPlan cardLoadPlan = LoadPlanStructureAssertionHelper.INSTANCE.buildLoadPlan( sf, cardPersister );
assertEquals( LoadPlan.Disposition.ENTITY_LOADER, cardLoadPlan.getDisposition() );
assertEquals( 1, cardLoadPlan.getReturns().size() );
// Card should have one fetch, the fields collection
assertEquals( 1, cardReturn.getFetches().length );
final CollectionFetch fieldsFetch = assertTyping( CollectionFetch.class, cardReturn.getFetches()[0] );
assertNotNull( fieldsFetch.getElementGraph() );
// Check the root EntityReturn(Card)
final EntityReturn cardReturn = assertTyping( EntityReturn.class, cardLoadPlan.getReturns().get( 0 ) );
assertFalse( cardReturn.getIdentifierDescription().hasFetches() );
// the Card.fields collection has entity elements of type CardField...
final CollectionFetchableElementEntityGraph cardFieldElementGraph = assertTyping( CollectionFetchableElementEntityGraph.class, fieldsFetch.getElementGraph() );
// CardField should have no fetches
assertEquals( 0, cardFieldElementGraph.getFetches().length );
// But it should have 1 key-many-to-one fetch for Key (Card is already handled)
assertTrue( cardFieldElementGraph.getIdentifierDescription().hasFetches() );
final FetchSource cardFieldElementGraphIdAsFetchSource = assertTyping(
FetchSource.class,
cardFieldElementGraph.getIdentifierDescription()
);
assertEquals( 1, cardFieldElementGraphIdAsFetchSource.getFetches().length );
// Card should have one fetch, the fields collection
assertEquals( 1, cardReturn.getFetches().length );
final CollectionFetch fieldsFetch = assertTyping( CollectionFetch.class, cardReturn.getFetches()[0] );
assertNotNull( fieldsFetch.getElementGraph() );
// BidirectionalEntityFetch circularCardFetch = assertTyping(
// BidirectionalEntityFetch.class,
// fieldsElementCompositeIdFetch.getFetches()[0]
// );
// assertSame( circularCardFetch.getTargetEntityReference(), cardReturn );
// the Card.fields collection has entity elements of type CardField...
final CollectionFetchableElementEntityGraph cardFieldElementGraph = assertTyping( CollectionFetchableElementEntityGraph.class, fieldsFetch.getElementGraph() );
// CardField should have no fetches
assertEquals( 0, cardFieldElementGraph.getFetches().length );
// But it should have 1 key-many-to-one fetch for Key (Card is already handled)
assertTrue( cardFieldElementGraph.getIdentifierDescription().hasFetches() );
final FetchSource cardFieldElementGraphIdAsFetchSource = assertTyping(
FetchSource.class,
cardFieldElementGraph.getIdentifierDescription()
);
assertEquals( 1, cardFieldElementGraphIdAsFetchSource.getFetches().length );
// the fetch above is to the other key-many-to-one for CardField.primaryKey composite: key
EntityFetch keyFetch = assertTyping(
EntityFetch.class,
cardFieldElementGraphIdAsFetchSource.getFetches()[0]
);
assertEquals( Key.class.getName(), keyFetch.getEntityPersister().getEntityName() );
// BidirectionalEntityFetch circularCardFetch = assertTyping(
// BidirectionalEntityFetch.class,
// fieldsElementCompositeIdFetch.getFetches()[0]
// );
// assertSame( circularCardFetch.getTargetEntityReference(), cardReturn );
// the fetch above is to the other key-many-to-one for CardField.primaryKey composite: key
EntityFetch keyFetch = assertTyping(
EntityFetch.class,
cardFieldElementGraphIdAsFetchSource.getFetches()[0]
);
assertEquals( Key.class.getName(), keyFetch.getEntityPersister().getEntityName() );
}
finally {
sf.close();
}
}
@Test
@ -212,7 +245,13 @@ public class LoadPlanStructureAssertionTest extends BaseUnitTestCase {
Configuration cfg = new Configuration();
cfg.addResource( "org/hibernate/test/immutable/entitywithmutablecollection/inverse/ContractVariation.hbm.xml" );
SessionFactoryImplementor sf = (SessionFactoryImplementor) cfg.buildSessionFactory();
doCompare( sf, (OuterJoinLoadable) sf.getClassMetadata( org.hibernate.test.immutable.entitywithmutablecollection.Contract.class ) );
try {
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()
.addAnnotatedClass( TestCourse.class )
.buildSessionFactory();
final EntityPersister ep = (EntityPersister) sf.getClassMetadata( TestCourse.class );
MetamodelGraphWalker.visitEntity( new LoggingAssociationVisitationStrategy(), ep );
try {
final EntityPersister ep = (EntityPersister) sf.getClassMetadata( TestCourse.class );
MetamodelGraphWalker.visitEntity( new LoggingAssociationVisitationStrategy(), ep );
}
finally {
sf.close();
}
}
}

View File

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