HHH-7841 - Redesign Loader

This commit is contained in:
Gail Badner 2013-05-21 00:51:15 -07:00
parent a03d44f290
commit b846fa35b5
29 changed files with 326 additions and 76 deletions

View File

@ -58,7 +58,7 @@ public class EntityJoinableAssociationImpl extends AbstractJoinableAssociationIm
hasRestriction,
enabledFilters
);
this.joinableType = entityFetch.getAssociationType();
this.joinableType = entityFetch.getEntityType();
this.joinable = (Joinable) entityFetch.getEntityPersister();
}

View File

@ -64,7 +64,6 @@ public class LoadPlanBuildingHelper {
LockMode.NONE, // todo : for now
fetchOwner,
attributeDefinition.getName(),
(EntityType) attributeDefinition.getType(),
fetchStrategy
);
}

View File

@ -36,11 +36,17 @@ import org.hibernate.persister.walking.spi.CompositionDefinition;
import org.hibernate.type.Type;
/**
* This is a class for fetch owners, providing functionality related to the owned
* fetches.
*
* @author Steve Ebersole
* @author Gail Badner
*/
public abstract class AbstractFetchOwner extends AbstractPlanNode implements FetchOwner {
// TODO: I removed lockMode from this method because I *think* it only relates to EntityFetch and EntityReturn.
// lockMode should be moved back here if it applies to all fetch owners.
private List<Fetch> fetches;
public AbstractFetchOwner(SessionFactoryImplementor factory) {
@ -55,17 +61,18 @@ public abstract class AbstractFetchOwner extends AbstractPlanNode implements Fet
* A "copy" constructor. Used while making clones/copies of this.
*
* @param original - the original object to copy.
* @param copyContext - the copy context.
*/
protected AbstractFetchOwner(AbstractFetchOwner original, CopyContext copyContext) {
super( original );
validate();
// TODO: I don't think this is correct; shouldn't the fetches from original be copied into this???
copyContext.getReturnGraphVisitationStrategy().startingFetches( original );
if ( fetches == null || fetches.size() == 0 ) {
this.fetches = Collections.emptyList();
}
else {
// TODO: don't think this is correct...
List<Fetch> fetchesCopy = new ArrayList<Fetch>();
for ( Fetch fetch : fetches ) {
fetchesCopy.add( fetch.makeCopy( copyContext, this ) );
@ -75,6 +82,7 @@ public abstract class AbstractFetchOwner extends AbstractPlanNode implements Fet
copyContext.getReturnGraphVisitationStrategy().finishingFetches( original );
}
@Override
public void addFetch(Fetch fetch) {
if ( fetch.getOwner() != this ) {
throw new IllegalArgumentException( "Fetch and owner did not match" );
@ -92,6 +100,10 @@ public abstract class AbstractFetchOwner extends AbstractPlanNode implements Fet
return fetches == null ? NO_FETCHES : fetches.toArray( new Fetch[ fetches.size() ] );
}
/**
* Abstract method returning the delegate for obtaining details about an owned fetch.
* @return the delegate
*/
protected abstract FetchOwnerDelegate getFetchOwnerDelegate();
@Override

View File

@ -30,7 +30,10 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.PropertyPath;
/**
* Represents a singular attribute that is both a {@link FetchOwner} and a {@link Fetch}.
*
* @author Steve Ebersole
* @author Gail Badner
*/
public abstract class AbstractSingularAttributeFetch extends AbstractFetchOwner implements Fetch {
private final FetchOwner owner;
@ -39,6 +42,14 @@ public abstract class AbstractSingularAttributeFetch extends AbstractFetchOwner
private final PropertyPath propertyPath;
/**
* Constructs an {@link AbstractSingularAttributeFetch} object.
*
* @param factory - the session factory.
* @param owner - the fetch owner for this fetch.
* @param ownerProperty - the owner's property referring to this fetch.
* @param fetchStrategy - the fetch strategy for this fetch.
*/
public AbstractSingularAttributeFetch(
SessionFactoryImplementor factory,
FetchOwner owner,

View File

@ -12,7 +12,10 @@ import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
import org.hibernate.type.CompositeType;
/**
* Represents the {@link FetchOwner} for a composite collection element.
*
* @author Steve Ebersole
* @author Gail Badner
*/
public class CompositeElementGraph extends AbstractFetchOwner implements FetchableCollectionElement {
private final CollectionReference collectionReference;
@ -20,6 +23,13 @@ public class CompositeElementGraph extends AbstractFetchOwner implements Fetchab
private final CollectionPersister collectionPersister;
private final FetchOwnerDelegate fetchOwnerDelegate;
/**
* Constructs a {@link CompositeElementGraph}.
*
* @param sessionFactory - the session factory.
* @param collectionReference - the collection reference.
* @param collectionPath - the {@link PropertyPath} for the collection.
*/
public CompositeElementGraph(
SessionFactoryImplementor sessionFactory,
CollectionReference collectionReference,

View File

@ -29,22 +29,29 @@ import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
import org.hibernate.loader.spi.ResultSetProcessingContext;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
import org.hibernate.persister.walking.spi.CompositionDefinition;
import org.hibernate.type.CompositeType;
/**
* Represents a {@link Fetch} for a composite attribute as well as a
* {@link FetchOwner} for any sub-attributes fetches.
*
* @author Steve Ebersole
* @author Gail Badner
*/
public class CompositeFetch extends AbstractSingularAttributeFetch {
public static final FetchStrategy FETCH_PLAN = new FetchStrategy( FetchTiming.IMMEDIATE, FetchStyle.JOIN );
private final FetchOwnerDelegate delegate;
/**
* Constructs a {@link CompositeFetch} object.
*
* @param sessionFactory - the session factory.
* @param owner - the fetch owner for this fetch.
* @param ownerProperty - the owner's property referring to this fetch.
*/
public CompositeFetch(
SessionFactoryImplementor sessionFactory,
FetchOwner owner,
@ -72,33 +79,6 @@ public class CompositeFetch extends AbstractSingularAttributeFetch {
return getOwner().retrieveFetchSourcePersister();
}
@Override
public CollectionFetch buildCollectionFetch(
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy,
LoadPlanBuildingContext loadPlanBuildingContext) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public EntityFetch buildEntityFetch(
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy,
LoadPlanBuildingContext loadPlanBuildingContext) {
return LoadPlanBuildingHelper.buildStandardEntityFetch(
this,
attributeDefinition,
fetchStrategy,
loadPlanBuildingContext
);
}
@Override
public CompositeFetch buildCompositeFetch(
CompositionDefinition attributeDefinition, LoadPlanBuildingContext loadPlanBuildingContext) {
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
}
@Override
public void hydrate(ResultSet resultSet, ResultSetProcessingContext context) throws SQLException {
//To change body of implemented methods use File | Settings | File Templates.

View File

@ -32,6 +32,9 @@ import org.hibernate.type.CompositeType;
import org.hibernate.type.Type;
/**
* This interface provides a delegate for a composite fetch owner to
* obtain details about an owned sub-attribute fetch.
*
* @author Gail Badner
*/
public class CompositeFetchOwnerDelegate implements FetchOwnerDelegate {
@ -39,6 +42,12 @@ public class CompositeFetchOwnerDelegate implements FetchOwnerDelegate {
private final CompositeType compositeType;
private final String[] columnNames;
/**
* Constructs a {@link CompositeFetchOwnerDelegate}.
* @param sessionFactory - the session factory.
* @param compositeType - the composite type.
* @param columnNames - the column names used by sub-attribute fetches.
*/
public CompositeFetchOwnerDelegate(
SessionFactoryImplementor sessionFactory,
CompositeType compositeType,

View File

@ -12,7 +12,10 @@ import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
import org.hibernate.type.CompositeType;
/**
* Represents the {@link FetchOwner} for a composite collection index.
*
* @author Steve Ebersole
* @author Gail Badner
*/
public class CompositeIndexGraph extends AbstractFetchOwner implements FetchableCollectionIndex {
private final CollectionReference collectionReference;
@ -20,14 +23,21 @@ public class CompositeIndexGraph extends AbstractFetchOwner implements Fetchable
private final CollectionPersister collectionPersister;
private final FetchOwnerDelegate fetchOwnerDelegate;
/**
* Constructs a {@link CompositeElementGraph}.
*
* @param sessionFactory - the session factory.
* @param collectionReference - the collection reference.
* @param collectionPath - the {@link PropertyPath} for the collection.
*/
public CompositeIndexGraph(
SessionFactoryImplementor sessionFactory,
CollectionReference collectionReference,
PropertyPath propertyPath) {
PropertyPath collectionPath) {
super( sessionFactory );
this.collectionReference = collectionReference;
this.collectionPersister = collectionReference.getCollectionPersister();
this.propertyPath = propertyPath.append( "<index>" );
this.propertyPath = collectionPath.append( "<index>" );
this.fetchOwnerDelegate = new CompositeFetchOwnerDelegate(
sessionFactory,
(CompositeType) collectionPersister.getIndexType(),
@ -52,6 +62,7 @@ public class CompositeIndexGraph extends AbstractFetchOwner implements Fetchable
return collectionPersister.getOwnerEntityPersister();
}
@Override
public CollectionReference getCollectionReference() {
return collectionReference;
}
@ -71,6 +82,7 @@ public class CompositeIndexGraph extends AbstractFetchOwner implements Fetchable
return fetchOwnerDelegate;
}
@Override
public CollectionFetch buildCollectionFetch(
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy,

View File

@ -9,6 +9,9 @@ import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.AssociationType;
/**
* Represents the {@link FetchOwner} for a collection element that is
* an entity association type.
*
* @author Steve Ebersole
*/
public class EntityElementGraph extends AbstractFetchOwner implements FetchableCollectionElement, EntityReference {
@ -21,6 +24,13 @@ public class EntityElementGraph extends AbstractFetchOwner implements FetchableC
private IdentifierDescription identifierDescription;
/**
* Constructs an {@link EntityElementGraph}.
*
* @param sessionFactory - the session factory.
* @param collectionReference - the collection reference.
* @param collectionPath - the {@link PropertyPath} for the collection.
*/
public EntityElementGraph(
SessionFactoryImplementor sessionFactory,
CollectionReference collectionReference,

View File

@ -37,28 +37,39 @@ import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.EntityType;
/**
* Represents a {@link Fetch} for an entity association attribute as well as a
* {@link FetchOwner} of the entity association sub-attribute fetches.
* @author Steve Ebersole
*/
public class EntityFetch extends AbstractSingularAttributeFetch implements EntityReference, Fetch {
private final EntityType associationType;
private final EntityPersister persister;
private final LockMode lockMode;
private final FetchOwnerDelegate fetchOwnerDelegate;
private IdentifierDescription identifierDescription;
/**
* Constructs an {@link EntityFetch} object.
*
* @param sessionFactory - the session factory.
* @param lockMode - the lock mode.
* @param owner - the fetch owner for this fetch.
* @param ownerProperty - the owner's property referring to this fetch.
* @param fetchStrategy - the fetch strategy for this fetch.
*/
public EntityFetch(
SessionFactoryImplementor sessionFactory,
LockMode lockMode,
FetchOwner owner,
String ownerProperty,
EntityType entityType,
FetchStrategy fetchStrategy) {
super( sessionFactory, owner, ownerProperty, fetchStrategy );
this.associationType = entityType;
this.persister = sessionFactory.getEntityPersister( associationType.getAssociatedEntityName() );
this.persister = sessionFactory.getEntityPersister(
getEntityType().getAssociatedEntityName()
);
this.lockMode = lockMode;
this.fetchOwnerDelegate = new EntityFetchOwnerDelegate( persister );
}
@ -71,14 +82,17 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit
*/
protected EntityFetch(EntityFetch original, CopyContext copyContext, FetchOwner fetchOwnerCopy) {
super( original, copyContext, fetchOwnerCopy );
this.associationType = original.associationType;
this.persister = original.persister;
this.lockMode = original.lockMode;
this.fetchOwnerDelegate = original.fetchOwnerDelegate;
}
public EntityType getAssociationType() {
return associationType;
/**
* Returns the entity type for this fetch.
* @return the entity type for this fetch.
*/
public final EntityType getEntityType() {
return (EntityType) getOwner().getType( this );
}
@Override
@ -134,12 +148,12 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit
entityKey = identifierDescription.resolve( resultSet, context );
if ( entityKey == null ) {
// register the non-existence (though only for one-to-one associations)
if ( associationType.isOneToOne() ) {
if ( getEntityType().isOneToOne() ) {
// first, find our owner's entity-key...
final EntityKey ownersEntityKey = context.getIdentifierResolutionContext( (EntityReference) getOwner() ).getEntityKey();
if ( ownersEntityKey != null ) {
context.getSession().getPersistenceContext()
.addNullProperty( ownersEntityKey, associationType.getPropertyName() );
.addNullProperty( ownersEntityKey, getEntityType().getPropertyName() );
}
}
}
@ -154,6 +168,16 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit
return entityKey;
}
/**
* Resolve any fetches required to resolve the identifier as well
* as the entity key for this fetch..
*
* @param resultSet - the result set.
* @param context - the result set processing context.
* @return the entity key for this fetch.
*
* @throws SQLException
*/
public EntityKey resolveInIdentifier(ResultSet resultSet, ResultSetProcessingContext context) throws SQLException {
// todo : may not need to do this if entitykey is already part of the resolution context
@ -219,7 +243,7 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit
acquiredLockMode,
persister,
getFetchStrategy().getTiming() == FetchTiming.IMMEDIATE,
associationType
getEntityType()
);
// materialize associations (and initialize the object) later

View File

@ -30,11 +30,19 @@ import org.hibernate.type.AssociationType;
import org.hibernate.type.Type;
/**
* This interface provides a delegate for an entity fetch owner to
* obtain details about an owned attribute fetch.
*
* @author Gail Badner
*/
public class EntityFetchOwnerDelegate implements FetchOwnerDelegate {
private final EntityPersister entityPersister;
/**
* Constructs an {@link EntityFetchOwnerDelegate}.
*
* @param entityPersister - the entity persister.
*/
public EntityFetchOwnerDelegate(EntityPersister entityPersister) {
this.entityPersister = entityPersister;
}

View File

@ -32,6 +32,8 @@ import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.AssociationType;
/**
* Represents the {@link FetchOwner} for a collection index that is an entity.
*
* @author Steve Ebersole
*/
public class EntityIndexGraph extends AbstractFetchOwner implements FetchableCollectionIndex, EntityReference {
@ -44,6 +46,13 @@ public class EntityIndexGraph extends AbstractFetchOwner implements FetchableCol
private IdentifierDescription identifierDescription;
/**
* Constructs an {@link EntityIndexGraph}.
*
* @param sessionFactory - the session factory.
* @param collectionReference - the collection reference.
* @param collectionPath - the {@link PropertyPath} for the collection.
*/
public EntityIndexGraph(
SessionFactoryImplementor sessionFactory,
CollectionReference collectionReference,
@ -67,6 +76,9 @@ public class EntityIndexGraph extends AbstractFetchOwner implements FetchableCol
this.fetchOwnerDelegate = original.fetchOwnerDelegate;
}
/**
* TODO: Does lock mode apply to a collection index that is an entity?
*/
@Override
public LockMode getLockMode() {
return null;
@ -111,6 +123,11 @@ public class EntityIndexGraph extends AbstractFetchOwner implements FetchableCol
return new EntityIndexGraph( this, copyContext );
}
@Override
public CollectionReference getCollectionReference() {
return collectionReference;
}
@Override
protected FetchOwnerDelegate getFetchOwnerDelegate() {
return fetchOwnerDelegate;

View File

@ -38,13 +38,18 @@ import org.hibernate.persister.entity.EntityPersister;
import static org.hibernate.loader.spi.ResultSetProcessingContext.IdentifierResolutionContext;
/**
* Represents an entity return value in the query results. Not the same
* as a result (column) in the JDBC ResultSet!
*
* @see Return
*
* @author Steve Ebersole
*/
public class EntityReturn extends AbstractFetchOwner implements Return, EntityReference, CopyableReturn {
private final EntityPersister persister;
private final PropertyPath propertyPath = new PropertyPath(); // its a root
private final PropertyPath propertyPath = new PropertyPath(); // it's a root
private final LockMode lockMode;
@ -52,6 +57,13 @@ public class EntityReturn extends AbstractFetchOwner implements Return, EntityRe
private IdentifierDescription identifierDescription;
/**
* Construct an {@link EntityReturn}.
*
* @param sessionFactory - the session factory.
* @param lockMode - the lock mode.
* @param entityName - the entity name.
*/
public EntityReturn(
SessionFactoryImplementor sessionFactory,
LockMode lockMode,

View File

@ -52,10 +52,25 @@ public interface Fetch extends CopyableFetch {
*/
public String getOwnerPropertyName();
/**
* Is this fetch nullable?
*
* @return true, if this fetch is nullable; false, otherwise.
*/
public boolean isNullable();
/**
* Gets the column names used for this fetch.
*
* @return the column names used for this fetch.
*/
public String[] getColumnNames();
/**
* Gets the fetch strategy for this fetch.
*
* @return the fetch strategy for this fetch.
*/
public FetchStrategy getFetchStrategy();
/**

View File

@ -57,10 +57,31 @@ public interface FetchOwner {
*/
public Fetch[] getFetches();
/**
* Returns the type of the specified fetch.
*
* @param fetch - the owned fetch.
*
* @return the type of the specified fetch.
*/
public Type getType(Fetch fetch);
/**
* Is the specified fetch nullable?
*
* @param fetch - the owned fetch.
*
* @return true, if the fetch is nullable; false, otherwise.
*/
public boolean isNullable(Fetch fetch);
/**
* Returns the column names used for loading the specified fetch.
*
* @param fetch - the owned fetch.
*
* @return the column names used for loading the specified fetch.
*/
public String[] getColumnNames(Fetch fetch);
/**

View File

@ -26,13 +26,36 @@ package org.hibernate.loader.plan.spi;
import org.hibernate.type.Type;
/**
* This interface provides a delegate for a fetch owner to obtain details about an owned fetch.
*
* @author Gail Badner
*/
public interface FetchOwnerDelegate {
/**
* Is the specified fetch nullable?
*
* @param fetch - the owned fetch.
*
* @return true, if the fetch is nullable; false, otherwise.
*/
public boolean isNullable(Fetch fetch);
/**
* Returns the type of the specified fetch.
*
* @param fetch - the owned fetch.
*
* @return the type of the specified fetch.
*/
public Type getType(Fetch fetch);
/**
* Returns the column names used for loading the specified fetch.
*
* @param fetch - the owned fetch.
*
* @return the column names used for loading the specified fetch.
*/
public String[] getColumnNames(Fetch fetch);
}

View File

@ -23,7 +23,6 @@
*/
package org.hibernate.loader.plan.spi;
import org.hibernate.persister.collection.CollectionPersister;
/**
* @author Steve Ebersole
@ -32,5 +31,9 @@ public interface FetchableCollectionElement extends FetchOwner, CopyableReturn {
@Override
public FetchableCollectionElement makeCopy(CopyContext copyContext);
/**
* Returns the collection reference.
* @return the collection reference.
*/
public CollectionReference getCollectionReference();
}

View File

@ -31,4 +31,10 @@ package org.hibernate.loader.plan.spi;
public interface FetchableCollectionIndex extends FetchOwner, CopyableReturn {
@Override
public FetchableCollectionIndex makeCopy(CopyContext copyContext);
/**
* Returns the collection reference.
* @return the collection reference.
*/
public CollectionReference getCollectionReference();
}

View File

@ -69,8 +69,8 @@ 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.CompositionElementDefinition;
import org.hibernate.persister.walking.spi.EntityDefinition;
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
import org.hibernate.persister.walking.spi.WalkingException;
@ -319,7 +319,7 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
}
@Override
public void startingCompositeElement(CompositionElementDefinition compositeElementDefinition) {
public void startingCompositeCollectionElement(CompositeCollectionElementDefinition compositeElementDefinition) {
System.out.println(
String.format(
"%s Starting composite collection element for (%s)",
@ -330,7 +330,7 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
}
@Override
public void finishingCompositeElement(CompositionElementDefinition compositeElementDefinition) {
public void finishingCompositeCollectionElement(CompositeCollectionElementDefinition compositeElementDefinition) {
// pop the current fetch owner, and make sure what we just popped represents this composition
final FetchOwner poppedFetchOwner = popFromStack();

View File

@ -86,8 +86,8 @@ import org.hibernate.persister.walking.spi.AttributeSource;
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.CompositionElementDefinition;
import org.hibernate.persister.walking.spi.EntityDefinition;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.sql.Alias;
@ -2010,15 +2010,13 @@ public abstract class AbstractCollectionPersister
}
@Override
public CompositionElementDefinition toCompositeElementDefinition() {
final String propertyName = role.substring( entityName.length() + 1 );
final int propertyIndex = ownerPersister.getEntityMetamodel().getPropertyIndex( propertyName );
public CompositeCollectionElementDefinition toCompositeElementDefinition() {
if ( ! getType().isComponentType() ) {
throw new IllegalStateException( "Cannot treat entity collection element type as composite" );
}
return new CompositionElementDefinition() {
return new CompositeCollectionElementDefinition() {
@Override
public String getName() {
return "";
@ -2038,7 +2036,7 @@ public abstract class AbstractCollectionPersister
@Override
public Iterable<AttributeDefinition> getAttributes() {
return CompositionSingularSubAttributesHelper.getCompositionElementSubAttributes( this );
return CompositionSingularSubAttributesHelper.getCompositeCollectionElementSubAttributes( this );
}
@Override

View File

@ -1,3 +1,26 @@
/*
* 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.persister.walking.internal;
import java.util.Iterator;
@ -20,8 +43,8 @@ import org.hibernate.persister.walking.spi.AssociationKey;
import org.hibernate.persister.walking.spi.AttributeDefinition;
import org.hibernate.persister.walking.spi.AttributeSource;
import org.hibernate.persister.walking.spi.CollectionDefinition;
import org.hibernate.persister.walking.spi.CompositeCollectionElementDefinition;
import org.hibernate.persister.walking.spi.CompositionDefinition;
import org.hibernate.persister.walking.spi.CompositionElementDefinition;
import org.hibernate.persister.walking.spi.EntityDefinition;
import org.hibernate.persister.walking.spi.WalkingException;
import org.hibernate.type.AssociationType;
@ -29,10 +52,22 @@ import org.hibernate.type.CompositeType;
import org.hibernate.type.Type;
/**
* A helper for getting attributes from a composition that is known
* to have only singular attributes; for example, sub-attributes of a
* composite ID or a composite collection element.
*
* TODO: This should be refactored into a delegate and renamed.
*
* @author Gail Badner
*/
public class CompositionSingularSubAttributesHelper {
/**
* Get composite ID sub-attribute definitions.
*
* @param entityPersister - the entity persister.
* @return composite ID sub-attribute definitions.
*/
public static Iterable<AttributeDefinition> getIdentifierSubAttributes(
final AbstractEntityPersister entityPersister) {
return getSingularSubAttributes(
@ -44,8 +79,13 @@ public class CompositionSingularSubAttributesHelper {
);
}
public static Iterable<AttributeDefinition> getCompositionElementSubAttributes(
CompositionElementDefinition compositionElementDefinition) {
/**
* Get sub-attribute definitions for a composite collection element.
* @param compositionElementDefinition - composite collection element definition.
* @return sub-attribute definitions for a composite collection element.
*/
public static Iterable<AttributeDefinition> getCompositeCollectionElementSubAttributes(
CompositeCollectionElementDefinition compositionElementDefinition) {
final QueryableCollection collectionPersister =
(QueryableCollection) compositionElementDefinition.getCollectionDefinition().getCollectionPersister();
return getSingularSubAttributes(

View File

@ -55,8 +55,8 @@ public interface AssociationVisitationStrategy {
public void startingComposite(CompositionDefinition compositionDefinition);
public void finishingComposite(CompositionDefinition compositionDefinition);
public void startingCompositeElement(CompositionElementDefinition compositionElementDefinition);
public void finishingCompositeElement(CompositionElementDefinition compositionElementDefinition);
public void startingCompositeCollectionElement(CompositeCollectionElementDefinition compositionElementDefinition);
public void finishingCompositeCollectionElement(CompositeCollectionElementDefinition compositionElementDefinition);
public boolean startingAttribute(AttributeDefinition attributeDefinition);
public void finishingAttribute(AttributeDefinition attributeDefinition);

View File

@ -26,14 +26,49 @@ package org.hibernate.persister.walking.spi;
import org.hibernate.type.Type;
/**
* Represents a collection element.
*
* @author Steve Ebersole
*/
public interface CollectionElementDefinition {
/**
* Returns the collection definition.
* @return the collection definition.
*/
public CollectionDefinition getCollectionDefinition();
/**
* Returns the collection element type.
* @return the collection element type
*/
public Type getType();
/**
* If the element type returned by {@link #getType()} is an
* {@link org.hibernate.type.EntityType}, then the entity
* definition for the collection element is returned;
* otherwise, IllegalStateException is thrown.
*
* @return the entity definition for the collection element.
*
* @throws IllegalStateException if the collection element type
* returned by {@link #getType()} is not of type
* {@link org.hibernate.type.EntityType}.
*/
public EntityDefinition toEntityDefinition();
public CompositionElementDefinition toCompositeElementDefinition();
/**
* If the element type returned by {@link #getType()} is a
* {@link org.hibernate.type.CompositeType}, then the composite
* element definition for the collection element is returned;
* otherwise, IllegalStateException is thrown.
*
* @return the composite element definition for the collection element.
*
* @throws IllegalStateException if the collection element type
* returned by {@link #getType()} is not of type
* {@link org.hibernate.type.CompositeType}.
*/
public CompositeCollectionElementDefinition toCompositeElementDefinition();
}

View File

@ -24,8 +24,14 @@
package org.hibernate.persister.walking.spi;
/**
* The definition for a composite collection element.
*
* @author Gail Badner
*/
public interface CompositionElementDefinition extends CompositionDefinition{
public interface CompositeCollectionElementDefinition extends CompositionDefinition{
/**
* Returns the collection definition.
* @return the collection definition.
*/
public CollectionDefinition getCollectionDefinition();
}

View File

@ -202,7 +202,7 @@ public class MetadataDrivenModelGraphVisitor {
strategy.startingCollectionElements( elementDefinition );
if ( elementDefinition.getType().isComponentType() ) {
visitCompositeElementDefinition( elementDefinition.toCompositeElementDefinition() );
visitCompositeCollectionElementDefinition( elementDefinition.toCompositeElementDefinition() );
}
else if ( elementDefinition.getType().isEntityType() ) {
visitEntityDefinition( elementDefinition.toEntityDefinition() );
@ -211,12 +211,12 @@ public class MetadataDrivenModelGraphVisitor {
strategy.finishingCollectionElements( elementDefinition );
}
private void visitCompositeElementDefinition(CompositionElementDefinition compositionElementDefinition) {
strategy.startingCompositeElement( compositionElementDefinition );
private void visitCompositeCollectionElementDefinition(CompositeCollectionElementDefinition compositionElementDefinition) {
strategy.startingCompositeCollectionElement( compositionElementDefinition );
visitAttributes( compositionElementDefinition );
strategy.finishingCompositeElement( compositionElementDefinition );
strategy.finishingCompositeCollectionElement( compositionElementDefinition );
}
private final Set<AssociationKey> visitedAssociationKeys = new HashSet<AssociationKey>();

View File

@ -30,6 +30,8 @@ import org.hibernate.tuple.NonIdentifierAttribute;
import org.hibernate.type.Type;
/**
* A base class for a sub-attribute of a composite, non-identifier attribute.
*
* @author Steve Ebersole
*/
public abstract class AbstractCompositeBasedAttribute

View File

@ -46,6 +46,8 @@ import static org.hibernate.engine.internal.JoinHelper.getLHSTableName;
import static org.hibernate.engine.internal.JoinHelper.getRHSColumnNames;
/**
* A base class for a composite, non-identifier attribute.
*
* @author Steve Ebersole
*/
public abstract class AbstractCompositionAttribute extends AbstractNonIdentifierAttribute implements

View File

@ -37,8 +37,8 @@ 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.CompositionElementDefinition;
import org.hibernate.persister.walking.spi.EntityDefinition;
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
import org.hibernate.persister.walking.spi.MetadataDrivenModelGraphVisitor;
@ -170,7 +170,7 @@ public class BasicWalkingTest extends BaseCoreFunctionalTestCase {
}
@Override
public void startingCompositeElement(CompositionElementDefinition compositionElementDefinition) {
public void startingCompositeCollectionElement(CompositeCollectionElementDefinition compositionElementDefinition) {
System.out.println(
String.format(
"%s Starting composite (%s)",
@ -181,7 +181,7 @@ public class BasicWalkingTest extends BaseCoreFunctionalTestCase {
}
@Override
public void finishingCompositeElement(CompositionElementDefinition compositionElementDefinition) {
public void finishingCompositeCollectionElement(CompositeCollectionElementDefinition compositionElementDefinition) {
System.out.println(
String.format(
"%s Finishing composite (%s)",

View File

@ -56,16 +56,11 @@ public class AdviceHelper {
);
}
else {
EntityType entityType = (EntityType) Helper.resolveType(
(SessionFactoryImplementor) attributeNode.entityManagerFactory().getSessionFactory(),
attributeNode.getAttribute()
);
return new EntityFetch(
(SessionFactoryImplementor) attributeNode.entityManagerFactory().getSessionFactory(),
LockMode.NONE,
fetchOwner,
attributeNode.getAttributeName(),
entityType,
new FetchStrategy( FetchTiming.IMMEDIATE, FetchStyle.SELECT )
);
}