From 043d618c030a02b36a62e02c767f1fdee7d6c93b Mon Sep 17 00:00:00 2001 From: Gail Badner Date: Thu, 16 May 2013 20:30:00 -0700 Subject: [PATCH] HHH-7841 - Redesign Loader HHH-7841 - Redesign Loader HHH-7841 - Redesign Loader HHH-7841 - Redesign Loader --- .../AbstractJoinableAssociationImpl.java | 3 +- .../CollectionJoinableAssociationImpl.java | 1 - .../EntityJoinableAssociationImpl.java | 2 - .../internal/EntityLoadQueryBuilderImpl.java | 4 - .../LoadQueryAliasResolutionContextImpl.java | 26 +-- .../loader/plan/spi/AbstractFetchOwner.java | 72 +++++- .../spi/AbstractSingularAttributeFetch.java | 14 +- .../loader/plan/spi/CollectionFetch.java | 12 + .../plan/spi/CompositeElementGraph.java | 81 ++----- .../loader/plan/spi/CompositeFetch.java | 18 +- .../plan/spi/CompositeFetchOwnerDelegate.java | 98 ++++++++ .../loader/plan/spi/CompositeIndexGraph.java | 84 ++----- .../loader/plan/spi/EntityElementGraph.java | 88 ++------ .../loader/plan/spi/EntityFetch.java | 58 ++--- .../plan/spi/EntityFetchOwnerDelegate.java | 72 ++++++ .../loader/plan/spi/EntityIndexGraph.java | 81 +------ .../loader/plan/spi/EntityReturn.java | 56 ++--- .../org/hibernate/loader/plan/spi/Fetch.java | 4 + .../hibernate/loader/plan/spi/FetchOwner.java | 7 + .../loader/plan/spi/FetchOwnerDelegate.java | 38 ++++ .../plan/spi/FetchableCollectionElement.java | 4 + .../AbstractLoadPlanBuilderStrategy.java | 133 ++++++++++- .../AbstractCollectionPersister.java | 41 +++- .../entity/AbstractEntityPersister.java | 7 - ...ompositionSingularSubAttributesHelper.java | 212 ++++++++++++++++++ .../EntityIdentifierDefinitionHelper.java | 184 +-------------- .../spi/AssociationVisitationStrategy.java | 3 + .../spi/CollectionElementDefinition.java | 2 +- .../spi/CompositionElementDefinition.java | 31 +++ .../spi/MetadataDrivenModelGraphVisitor.java | 18 +- .../AbstractCompositeBasedAttribute.java | 6 +- ...java => AbstractCompositionAttribute.java} | 44 ++-- .../CompositeBasedAssociationAttribute.java | 2 +- .../CompositionBasedCompositionAttribute.java | 2 +- .../EntityBasedCompositionAttribute.java | 4 +- ...positeAttributeResultSetProcessorTest.java | 20 +- .../persister/walking/BasicWalkingTest.java | 23 ++ 37 files changed, 947 insertions(+), 608 deletions(-) create mode 100644 hibernate-core/src/main/java/org/hibernate/loader/plan/spi/CompositeFetchOwnerDelegate.java create mode 100644 hibernate-core/src/main/java/org/hibernate/loader/plan/spi/EntityFetchOwnerDelegate.java create mode 100644 hibernate-core/src/main/java/org/hibernate/loader/plan/spi/FetchOwnerDelegate.java create mode 100644 hibernate-core/src/main/java/org/hibernate/persister/walking/internal/CompositionSingularSubAttributesHelper.java create mode 100644 hibernate-core/src/main/java/org/hibernate/persister/walking/spi/CompositionElementDefinition.java rename hibernate-core/src/main/java/org/hibernate/tuple/component/{AbstractCompositionDefinition.java => AbstractCompositionAttribute.java} (79%) diff --git a/hibernate-core/src/main/java/org/hibernate/loader/internal/AbstractJoinableAssociationImpl.java b/hibernate-core/src/main/java/org/hibernate/loader/internal/AbstractJoinableAssociationImpl.java index 11bf50aaf5..acc41f7839 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/internal/AbstractJoinableAssociationImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/internal/AbstractJoinableAssociationImpl.java @@ -56,12 +56,11 @@ public abstract class AbstractJoinableAssociationImpl implements JoinableAssocia EntityReference currentEntityReference, CollectionReference currentCollectionReference, String withClause, - boolean isNullable, boolean hasRestriction, Map enabledFilters) throws MappingException { this.propertyPath = currentFetch.getPropertyPath(); if ( currentFetch.getFetchStrategy().getStyle() == FetchStyle.JOIN ) { - joinType = isNullable ? JoinType.LEFT_OUTER_JOIN : JoinType.INNER_JOIN; + joinType = currentFetch.isNullable() ? JoinType.LEFT_OUTER_JOIN : JoinType.INNER_JOIN; } else { joinType = JoinType.NONE; diff --git a/hibernate-core/src/main/java/org/hibernate/loader/internal/CollectionJoinableAssociationImpl.java b/hibernate-core/src/main/java/org/hibernate/loader/internal/CollectionJoinableAssociationImpl.java index df49038b35..254c1a9c33 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/internal/CollectionJoinableAssociationImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/internal/CollectionJoinableAssociationImpl.java @@ -56,7 +56,6 @@ public class CollectionJoinableAssociationImpl extends AbstractJoinableAssociati currentEntityReference, collectionFetch, withClause, - true, hasRestriction, enabledFilters ); diff --git a/hibernate-core/src/main/java/org/hibernate/loader/internal/EntityJoinableAssociationImpl.java b/hibernate-core/src/main/java/org/hibernate/loader/internal/EntityJoinableAssociationImpl.java index d52323bc09..34d22b56ba 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/internal/EntityJoinableAssociationImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/internal/EntityJoinableAssociationImpl.java @@ -48,7 +48,6 @@ public class EntityJoinableAssociationImpl extends AbstractJoinableAssociationIm EntityFetch entityFetch, CollectionReference currentCollectionReference, String withClause, - boolean isNullable, boolean hasRestriction, Map enabledFilters) throws MappingException { super( @@ -56,7 +55,6 @@ public class EntityJoinableAssociationImpl extends AbstractJoinableAssociationIm entityFetch, currentCollectionReference, withClause, - isNullable, hasRestriction, enabledFilters ); diff --git a/hibernate-core/src/main/java/org/hibernate/loader/internal/EntityLoadQueryBuilderImpl.java b/hibernate-core/src/main/java/org/hibernate/loader/internal/EntityLoadQueryBuilderImpl.java index 769f419583..aef90267f1 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/internal/EntityLoadQueryBuilderImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/internal/EntityLoadQueryBuilderImpl.java @@ -149,14 +149,10 @@ public class EntityLoadQueryBuilderImpl implements LoadQueryBuilder { @Override public void startingEntityFetch(EntityFetch entityFetch) { - final OuterJoinLoadable ownerPersister = (OuterJoinLoadable) entityFetch.getOwner().retrieveFetchSourcePersister(); - final int propertyNumber = ownerPersister.getEntityMetamodel().getPropertyIndex( entityFetch.getOwnerPropertyName() ); - final boolean isNullable = ownerPersister.isSubclassPropertyNullable( propertyNumber ); EntityJoinableAssociationImpl assoc = new EntityJoinableAssociationImpl( entityFetch, getCurrentCollectionReference(), "", // getWithClause( entityFetch.getPropertyPath() ) - isNullable, false, // hasRestriction( entityFetch.getPropertyPath() ) loadQueryInfluencers.getEnabledFilters() ); diff --git a/hibernate-core/src/main/java/org/hibernate/loader/internal/LoadQueryAliasResolutionContextImpl.java b/hibernate-core/src/main/java/org/hibernate/loader/internal/LoadQueryAliasResolutionContextImpl.java index d829669a29..193a7e42f5 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/internal/LoadQueryAliasResolutionContextImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/internal/LoadQueryAliasResolutionContextImpl.java @@ -27,7 +27,6 @@ import java.util.HashMap; import java.util.Map; import org.hibernate.cfg.NotYetImplementedException; -import org.hibernate.engine.internal.JoinHelper; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.internal.util.StringHelper; import org.hibernate.loader.CollectionAliases; @@ -36,6 +35,8 @@ import org.hibernate.loader.EntityAliases; import org.hibernate.loader.GeneratedCollectionAliases; import org.hibernate.loader.plan.spi.CollectionReference; import org.hibernate.loader.plan.spi.CollectionReturn; +import org.hibernate.loader.plan.spi.CompositeElementGraph; +import org.hibernate.loader.plan.spi.CompositeIndexGraph; import org.hibernate.loader.plan.spi.EntityReference; import org.hibernate.loader.plan.spi.EntityReturn; import org.hibernate.loader.plan.spi.Fetch; @@ -46,7 +47,6 @@ import org.hibernate.loader.spi.LoadQueryAliasResolutionContext; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.Loadable; -import org.hibernate.persister.entity.OuterJoinLoadable; import org.hibernate.type.EntityType; /** @@ -214,9 +214,18 @@ public class LoadQueryAliasResolutionContextImpl implements LoadQueryAliasResolu if ( EntityReference.class.isInstance( currentFetch.getOwner() ) ) { lhsAlias = resolveEntityTableAlias( (EntityReference) currentFetch.getOwner() ); } - else { - throw new NotYetImplementedException( "Cannot determine LHS alias for a FetchOwner that is not an EntityReference yet." ); + else if ( CompositeElementGraph.class.isInstance( currentFetch.getOwner() ) ) { + CompositeElementGraph compositeElementGraph = (CompositeElementGraph) currentFetch.getOwner(); + lhsAlias = resolveCollectionTableAlias( compositeElementGraph.getCollectionReference() ); } + else if ( CompositeIndexGraph.class.isInstance( currentFetch.getOwner() ) ) { + CompositeIndexGraph compositeIndexGraph = (CompositeIndexGraph) currentFetch.getOwner(); + lhsAlias = resolveCollectionTableAlias( compositeIndexGraph.getCollectionReference() ); + } + else { + throw new NotYetImplementedException( "Cannot determine LHS alias for FetchOwner." ); + } + final String[] aliasedLhsColumnNames = StringHelper.qualify( lhsAlias, currentFetch.getColumnNames() ); final String rhsAlias; if ( EntityReference.class.isInstance( currentFetch ) ) { rhsAlias = resolveEntityTableAlias( (EntityReference) currentFetch ); @@ -229,15 +238,6 @@ public class LoadQueryAliasResolutionContextImpl implements LoadQueryAliasResolu } // TODO: can't this be found in CollectionAliases or EntityAliases? should be moved to LoadQueryAliasResolutionContextImpl - final OuterJoinLoadable fetchSourcePersister = (OuterJoinLoadable) currentFetch.getOwner().retrieveFetchSourcePersister(); - final int propertyNumber = fetchSourcePersister.getEntityMetamodel().getPropertyIndex( currentFetch.getOwnerPropertyName() ); - final String[] aliasedLhsColumnNames = JoinHelper.getAliasedLHSColumnNames( - joinableAssociation.getAssociationType(), - lhsAlias, - propertyNumber, - fetchSourcePersister, - sessionFactory - ); aliases = new JoinableAssociationAliasesImpl( lhsAlias, aliasedLhsColumnNames, rhsAlias ); aliasesByJoinableAssociation.put( joinableAssociation, aliases ); diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/AbstractFetchOwner.java b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/AbstractFetchOwner.java index ffb5656f12..2e6293c1b5 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/AbstractFetchOwner.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/AbstractFetchOwner.java @@ -27,20 +27,24 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import org.hibernate.LockMode; +import org.hibernate.engine.FetchStrategy; import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper; +import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext; +import org.hibernate.persister.walking.spi.AssociationAttributeDefinition; +import org.hibernate.persister.walking.spi.CompositionDefinition; +import org.hibernate.type.Type; /** * @author Steve Ebersole + * @author Gail Badner */ public abstract class AbstractFetchOwner extends AbstractPlanNode implements FetchOwner { - private final LockMode lockMode; private List fetches; - public AbstractFetchOwner(SessionFactoryImplementor factory, LockMode lockMode) { + public AbstractFetchOwner(SessionFactoryImplementor factory) { super( factory ); - this.lockMode = lockMode; validate(); } @@ -50,11 +54,10 @@ public abstract class AbstractFetchOwner extends AbstractPlanNode implements Fet /** * A "copy" constructor. Used while making clones/copies of this. * - * @param original + * @param original - the original object to copy. */ protected AbstractFetchOwner(AbstractFetchOwner original, CopyContext copyContext) { super( original ); - this.lockMode = original.lockMode; validate(); copyContext.getReturnGraphVisitationStrategy().startingFetches( original ); @@ -62,6 +65,7 @@ public abstract class AbstractFetchOwner extends AbstractPlanNode implements Fet this.fetches = Collections.emptyList(); } else { + // TODO: don't think this is correct... List fetchesCopy = new ArrayList(); for ( Fetch fetch : fetches ) { fetchesCopy.add( fetch.makeCopy( copyContext, this ) ); @@ -71,11 +75,6 @@ public abstract class AbstractFetchOwner extends AbstractPlanNode implements Fet copyContext.getReturnGraphVisitationStrategy().finishingFetches( original ); } - public LockMode getLockMode() { - return lockMode; - } - - @Override public void addFetch(Fetch fetch) { if ( fetch.getOwner() != this ) { throw new IllegalArgumentException( "Fetch and owner did not match" ); @@ -92,4 +91,55 @@ public abstract class AbstractFetchOwner extends AbstractPlanNode implements Fet public Fetch[] getFetches() { return fetches == null ? NO_FETCHES : fetches.toArray( new Fetch[ fetches.size() ] ); } + + protected abstract FetchOwnerDelegate getFetchOwnerDelegate(); + + @Override + public boolean isNullable(Fetch fetch) { + return getFetchOwnerDelegate().isNullable( fetch ); + } + + @Override + public Type getType(Fetch fetch) { + return getFetchOwnerDelegate().getType( fetch ); + } + + @Override + public String[] getColumnNames(Fetch fetch) { + return getFetchOwnerDelegate().getColumnNames( fetch ); + } + + @Override + public CollectionFetch buildCollectionFetch( + AssociationAttributeDefinition attributeDefinition, + FetchStrategy fetchStrategy, + LoadPlanBuildingContext loadPlanBuildingContext) { + return LoadPlanBuildingHelper.buildStandardCollectionFetch( + this, + attributeDefinition, + fetchStrategy, + loadPlanBuildingContext + ); + } + + @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 ); + } + } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/AbstractSingularAttributeFetch.java b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/AbstractSingularAttributeFetch.java index ddb4b4491f..0b3689844d 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/AbstractSingularAttributeFetch.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/AbstractSingularAttributeFetch.java @@ -24,7 +24,6 @@ package org.hibernate.loader.plan.spi; import org.hibernate.HibernateException; -import org.hibernate.LockMode; import org.hibernate.engine.FetchStrategy; import org.hibernate.engine.FetchStyle; import org.hibernate.engine.spi.SessionFactoryImplementor; @@ -42,11 +41,10 @@ public abstract class AbstractSingularAttributeFetch extends AbstractFetchOwner public AbstractSingularAttributeFetch( SessionFactoryImplementor factory, - LockMode lockMode, FetchOwner owner, String ownerProperty, FetchStrategy fetchStrategy) { - super( factory, lockMode ); + super( factory ); this.owner = owner; this.ownerProperty = ownerProperty; this.fetchStrategy = fetchStrategy; @@ -77,6 +75,16 @@ public abstract class AbstractSingularAttributeFetch extends AbstractFetchOwner return ownerProperty; } + @Override + public boolean isNullable() { + return owner.isNullable( this ); + } + + @Override + public String[] getColumnNames() { + return owner.getColumnNames( this ); + } + @Override public FetchStrategy getFetchStrategy() { return fetchStrategy; diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/CollectionFetch.java b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/CollectionFetch.java index fef9cd1b65..242daf427c 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/CollectionFetch.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/CollectionFetch.java @@ -28,8 +28,10 @@ import java.sql.SQLException; import org.hibernate.LockMode; import org.hibernate.engine.FetchStrategy; +import org.hibernate.engine.internal.JoinHelper; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.loader.spi.ResultSetProcessingContext; +import org.hibernate.persister.entity.Joinable; import org.hibernate.type.CollectionType; /** @@ -74,6 +76,16 @@ public class CollectionFetch extends AbstractCollectionReference implements Fetc return getPropertyPath().getProperty(); } + @Override + public boolean isNullable() { + return true; + } + + @Override + public String[] getColumnNames() { + return getOwner().getColumnNames( this ); + } + @Override public FetchStrategy getFetchStrategy() { return fetchStrategy; diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/CompositeElementGraph.java b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/CompositeElementGraph.java index b1ddd79d30..e2d23540df 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/CompositeElementGraph.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/CompositeElementGraph.java @@ -1,29 +1,24 @@ package org.hibernate.loader.plan.spi; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - import org.hibernate.HibernateException; import org.hibernate.engine.FetchStrategy; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.loader.PropertyPath; -import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper; import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext; import org.hibernate.persister.collection.CollectionPersister; +import org.hibernate.persister.collection.QueryableCollection; 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; /** * @author Steve Ebersole */ -public class CompositeElementGraph extends AbstractPlanNode implements FetchableCollectionElement { +public class CompositeElementGraph extends AbstractFetchOwner implements FetchableCollectionElement { private final CollectionReference collectionReference; private final PropertyPath propertyPath; private final CollectionPersister collectionPersister; - - private List fetches; + private final FetchOwnerDelegate fetchOwnerDelegate; public CompositeElementGraph( SessionFactoryImplementor sessionFactory, @@ -34,39 +29,24 @@ public class CompositeElementGraph extends AbstractPlanNode implements Fetchable this.collectionReference = collectionReference; this.collectionPersister = collectionReference.getCollectionPersister(); this.propertyPath = collectionPath.append( "" ); + this.fetchOwnerDelegate = new CompositeFetchOwnerDelegate( + sessionFactory, + (CompositeType) collectionPersister.getElementType(), + ( (QueryableCollection) collectionPersister ).getElementColumnNames() + ); } public CompositeElementGraph(CompositeElementGraph original, CopyContext copyContext) { - super( original ); + super( original, copyContext ); this.collectionReference = original.collectionReference; this.collectionPersister = original.collectionPersister; this.propertyPath = original.propertyPath; - - copyContext.getReturnGraphVisitationStrategy().startingFetches( original ); - if ( fetches == null || fetches.size() == 0 ) { - this.fetches = Collections.emptyList(); - } - else { - List fetchesCopy = new ArrayList(); - for ( Fetch fetch : fetches ) { - fetchesCopy.add( fetch.makeCopy( copyContext, this ) ); - } - this.fetches = fetchesCopy; - } - copyContext.getReturnGraphVisitationStrategy().finishingFetches( original ); + this.fetchOwnerDelegate = original.fetchOwnerDelegate; } @Override - public void addFetch(Fetch fetch) { - if ( fetches == null ) { - fetches = new ArrayList(); - } - fetches.add( fetch ); - } - - @Override - public Fetch[] getFetches() { - return fetches == null ? NO_FETCHES : fetches.toArray( new Fetch[ fetches.size() ] ); + public CollectionReference getCollectionReference() { + return collectionReference; } @Override @@ -83,6 +63,16 @@ public class CompositeElementGraph extends AbstractPlanNode implements Fetchable return propertyPath; } + @Override + public CompositeElementGraph makeCopy(CopyContext copyContext) { + return new CompositeElementGraph( this, copyContext ); + } + + @Override + protected FetchOwnerDelegate getFetchOwnerDelegate() { + return fetchOwnerDelegate; + } + @Override public CollectionFetch buildCollectionFetch( AssociationAttributeDefinition attributeDefinition, @@ -90,29 +80,4 @@ public class CompositeElementGraph extends AbstractPlanNode implements Fetchable LoadPlanBuildingContext loadPlanBuildingContext) { throw new HibernateException( "Collection composite element cannot define collections" ); } - - @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 CompositeElementGraph makeCopy(CopyContext copyContext) { - return new CompositeElementGraph( this, copyContext ); - } } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/CompositeFetch.java b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/CompositeFetch.java index b002c7b567..c1c043308c 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/CompositeFetch.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/CompositeFetch.java @@ -25,8 +25,6 @@ package org.hibernate.loader.plan.spi; import java.sql.ResultSet; import java.sql.SQLException; - -import org.hibernate.LockMode; import org.hibernate.engine.FetchStrategy; import org.hibernate.engine.FetchStyle; import org.hibernate.engine.FetchTiming; @@ -37,6 +35,7 @@ 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; /** * @author Steve Ebersole @@ -44,15 +43,28 @@ import org.hibernate.persister.walking.spi.CompositionDefinition; public class CompositeFetch extends AbstractSingularAttributeFetch { public static final FetchStrategy FETCH_PLAN = new FetchStrategy( FetchTiming.IMMEDIATE, FetchStyle.JOIN ); + private final FetchOwnerDelegate delegate; + public CompositeFetch( SessionFactoryImplementor sessionFactory, FetchOwner owner, String ownerProperty) { - super( sessionFactory, LockMode.NONE, owner, ownerProperty, FETCH_PLAN ); + super( sessionFactory, owner, ownerProperty, FETCH_PLAN ); + this.delegate = new CompositeFetchOwnerDelegate( + sessionFactory, + (CompositeType) getOwner().getType( this ), + getOwner().getColumnNames( this ) + ); } public CompositeFetch(CompositeFetch original, CopyContext copyContext, FetchOwner fetchOwnerCopy) { super( original, copyContext, fetchOwnerCopy ); + this.delegate = original.getFetchOwnerDelegate(); + } + + @Override + protected FetchOwnerDelegate getFetchOwnerDelegate() { + return delegate; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/CompositeFetchOwnerDelegate.java b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/CompositeFetchOwnerDelegate.java new file mode 100644 index 0000000000..8c530eb5d2 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/CompositeFetchOwnerDelegate.java @@ -0,0 +1,98 @@ +/* + * 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.loader.plan.spi; + +import java.util.Arrays; + +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.internal.util.collections.ArrayHelper; +import org.hibernate.persister.walking.spi.WalkingException; +import org.hibernate.type.CompositeType; +import org.hibernate.type.Type; + +/** + * @author Gail Badner + */ +public class CompositeFetchOwnerDelegate implements FetchOwnerDelegate { + private final SessionFactoryImplementor sessionFactory; + private final CompositeType compositeType; + private final String[] columnNames; + + public CompositeFetchOwnerDelegate( + SessionFactoryImplementor sessionFactory, + CompositeType compositeType, + String[] columnNames) { + this.sessionFactory = sessionFactory; + this.compositeType = compositeType; + this.columnNames = columnNames; + } + + @Override + public boolean isNullable(Fetch fetch) { + return compositeType.getPropertyNullability()[ determinePropertyIndex( fetch ) ]; + } + + @Override + public Type getType(Fetch fetch) { + return compositeType.getSubtypes()[ determinePropertyIndex( fetch ) ]; + } + + @Override + public String[] getColumnNames(Fetch fetch) { + // TODO: probably want to cache this + int begin = 0; + String[] subColumnNames = null; + for ( int i = 0; i < compositeType.getSubtypes().length; i++ ) { + final int columnSpan = compositeType.getSubtypes()[i].getColumnSpan( sessionFactory ); + subColumnNames = ArrayHelper.slice( columnNames, begin, columnSpan ); + if ( compositeType.getPropertyNames()[ i ].equals( fetch.getOwnerPropertyName() ) ) { + break; + } + begin += columnSpan; + } + return subColumnNames; + } + + private int determinePropertyIndex(Fetch fetch) { + // TODO: probably want to cache this + final String[] subAttributeNames = compositeType.getPropertyNames(); + int subAttributeIndex = -1; + for ( int i = 0; i < subAttributeNames.length ; i++ ) { + if ( subAttributeNames[ i ].equals( fetch.getOwnerPropertyName() ) ) { + subAttributeIndex = i; + break; + } + } + if ( subAttributeIndex == -1 ) { + throw new WalkingException( + String.format( + "Owner property [%s] not found in composite properties [%s]", + fetch.getOwnerPropertyName(), + Arrays.asList( subAttributeNames ) + ) + ); + } + return subAttributeIndex; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/CompositeIndexGraph.java b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/CompositeIndexGraph.java index bccc7b1cd7..f4f4eb7fe4 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/CompositeIndexGraph.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/CompositeIndexGraph.java @@ -1,29 +1,24 @@ package org.hibernate.loader.plan.spi; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - import org.hibernate.HibernateException; import org.hibernate.engine.FetchStrategy; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.loader.PropertyPath; -import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper; import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext; import org.hibernate.persister.collection.CollectionPersister; +import org.hibernate.persister.collection.QueryableCollection; 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; /** * @author Steve Ebersole */ -public class CompositeIndexGraph extends AbstractPlanNode implements FetchableCollectionIndex { +public class CompositeIndexGraph extends AbstractFetchOwner implements FetchableCollectionIndex { private final CollectionReference collectionReference; private final PropertyPath propertyPath; private final CollectionPersister collectionPersister; - - private List fetches; + private final FetchOwnerDelegate fetchOwnerDelegate; public CompositeIndexGraph( SessionFactoryImplementor sessionFactory, @@ -33,39 +28,19 @@ public class CompositeIndexGraph extends AbstractPlanNode implements FetchableCo this.collectionReference = collectionReference; this.collectionPersister = collectionReference.getCollectionPersister(); this.propertyPath = propertyPath.append( "" ); + this.fetchOwnerDelegate = new CompositeFetchOwnerDelegate( + sessionFactory, + (CompositeType) collectionPersister.getIndexType(), + ( (QueryableCollection) collectionPersister ).getIndexColumnNames() + ); } protected CompositeIndexGraph(CompositeIndexGraph original, CopyContext copyContext) { - super( original ); + super( original, copyContext ); this.collectionReference = original.collectionReference; this.collectionPersister = original.collectionPersister; this.propertyPath = original.propertyPath; - - copyContext.getReturnGraphVisitationStrategy().startingFetches( original ); - if ( fetches == null || fetches.size() == 0 ) { - this.fetches = Collections.emptyList(); - } - else { - List fetchesCopy = new ArrayList(); - for ( Fetch fetch : fetches ) { - fetchesCopy.add( fetch.makeCopy( copyContext, this ) ); - } - this.fetches = fetchesCopy; - } - copyContext.getReturnGraphVisitationStrategy().finishingFetches( original ); - } - - @Override - public void addFetch(Fetch fetch) { - if ( fetches == null ) { - fetches = new ArrayList(); - } - fetches.add( fetch ); - } - - @Override - public Fetch[] getFetches() { - return fetches == null ? NO_FETCHES : fetches.toArray( new Fetch[ fetches.size() ] ); + this.fetchOwnerDelegate = original.fetchOwnerDelegate; } @Override @@ -77,12 +52,25 @@ public class CompositeIndexGraph extends AbstractPlanNode implements FetchableCo return collectionPersister.getOwnerEntityPersister(); } + public CollectionReference getCollectionReference() { + return collectionReference; + } + @Override public PropertyPath getPropertyPath() { return propertyPath; } @Override + public CompositeIndexGraph makeCopy(CopyContext copyContext) { + return new CompositeIndexGraph( this, copyContext ); + } + + @Override + protected FetchOwnerDelegate getFetchOwnerDelegate() { + return fetchOwnerDelegate; + } + public CollectionFetch buildCollectionFetch( AssociationAttributeDefinition attributeDefinition, FetchStrategy fetchStrategy, @@ -90,28 +78,4 @@ public class CompositeIndexGraph extends AbstractPlanNode implements FetchableCo throw new HibernateException( "Composite index cannot define collections" ); } - @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 CompositeIndexGraph makeCopy(CopyContext copyContext) { - return new CompositeIndexGraph( this, copyContext ); - } } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/EntityElementGraph.java b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/EntityElementGraph.java index d779a119ef..a3ccde17d7 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/EntityElementGraph.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/EntityElementGraph.java @@ -1,32 +1,23 @@ package org.hibernate.loader.plan.spi; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - import org.hibernate.LockMode; import org.hibernate.engine.FetchStrategy; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.loader.PropertyPath; -import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper; -import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; -import org.hibernate.persister.walking.spi.AssociationAttributeDefinition; -import org.hibernate.persister.walking.spi.CompositionDefinition; import org.hibernate.type.AssociationType; /** * @author Steve Ebersole */ -public class EntityElementGraph extends AbstractPlanNode implements FetchableCollectionElement, EntityReference { +public class EntityElementGraph extends AbstractFetchOwner implements FetchableCollectionElement, EntityReference { private final CollectionReference collectionReference; private final CollectionPersister collectionPersister; private final AssociationType elementType; private final EntityPersister elementPersister; private final PropertyPath propertyPath; - - private List fetches; + private final FetchOwnerDelegate fetchOwnerDelegate; private IdentifierDescription identifierDescription; @@ -40,30 +31,19 @@ public class EntityElementGraph extends AbstractPlanNode implements FetchableCol this.collectionPersister = collectionReference.getCollectionPersister(); this.elementType = (AssociationType) collectionPersister.getElementType(); this.elementPersister = (EntityPersister) this.elementType.getAssociatedJoinable( sessionFactory() ); - this.propertyPath = collectionPath.append( "" ); + this.propertyPath = collectionPath; + this.fetchOwnerDelegate = new EntityFetchOwnerDelegate( elementPersister ); } public EntityElementGraph(EntityElementGraph original, CopyContext copyContext) { - super( original ); + super( original, copyContext ); this.collectionReference = original.collectionReference; this.collectionPersister = original.collectionReference.getCollectionPersister(); this.elementType = original.elementType; this.elementPersister = original.elementPersister; this.propertyPath = original.propertyPath; - - copyContext.getReturnGraphVisitationStrategy().startingFetches( original ); - if ( fetches == null || fetches.size() == 0 ) { - this.fetches = Collections.emptyList(); - } - else { - List fetchesCopy = new ArrayList(); - for ( Fetch fetch : fetches ) { - fetchesCopy.add( fetch.makeCopy( copyContext, this ) ); - } - this.fetches = fetchesCopy; - } - copyContext.getReturnGraphVisitationStrategy().finishingFetches( original ); + this.fetchOwnerDelegate = original.fetchOwnerDelegate; } @Override @@ -86,19 +66,6 @@ public class EntityElementGraph extends AbstractPlanNode implements FetchableCol return identifierDescription; } - @Override - public void addFetch(Fetch fetch) { - if ( fetches == null ) { - fetches = new ArrayList(); - } - fetches.add( fetch ); - } - - @Override - public Fetch[] getFetches() { - return fetches == null ? NO_FETCHES : fetches.toArray( new Fetch[ fetches.size() ] ); - } - @Override public void validateFetchPlan(FetchStrategy fetchStrategy) { } @@ -113,39 +80,6 @@ public class EntityElementGraph extends AbstractPlanNode implements FetchableCol return propertyPath; } - @Override - public CollectionFetch buildCollectionFetch( - AssociationAttributeDefinition attributeDefinition, - FetchStrategy fetchStrategy, - LoadPlanBuildingContext loadPlanBuildingContext) { - return LoadPlanBuildingHelper.buildStandardCollectionFetch( - this, - attributeDefinition, - fetchStrategy, - loadPlanBuildingContext - ); - } - - @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 injectIdentifierDescription(IdentifierDescription identifierDescription) { this.identifierDescription = identifierDescription; @@ -156,8 +90,18 @@ public class EntityElementGraph extends AbstractPlanNode implements FetchableCol return new EntityElementGraph( this, copyContext ); } + @Override + public CollectionReference getCollectionReference() { + return collectionReference; + } + @Override public String toString() { return "EntityElementGraph(collection=" + collectionPersister.getRole() + ", type=" + elementPersister.getEntityName() + ")"; } + + @Override + protected FetchOwnerDelegate getFetchOwnerDelegate() { + return fetchOwnerDelegate; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/EntityFetch.java b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/EntityFetch.java index 124b3f7944..9842166561 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/EntityFetch.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/EntityFetch.java @@ -32,21 +32,19 @@ import org.hibernate.engine.FetchStrategy; import org.hibernate.engine.FetchTiming; import org.hibernate.engine.spi.EntityKey; 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.EntityType; /** * @author Steve Ebersole */ -public class EntityFetch extends AbstractSingularAttributeFetch implements EntityReference { +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; @@ -57,10 +55,12 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit String ownerProperty, EntityType entityType, FetchStrategy fetchStrategy) { - super( sessionFactory, lockMode, owner, ownerProperty, fetchStrategy ); + super( sessionFactory, owner, ownerProperty, fetchStrategy ); this.associationType = entityType; this.persister = sessionFactory.getEntityPersister( associationType.getAssociatedEntityName() ); + this.lockMode = lockMode; + this.fetchOwnerDelegate = new EntityFetchOwnerDelegate( persister ); } /** @@ -73,6 +73,8 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit super( original, copyContext, fetchOwnerCopy ); this.associationType = original.associationType; this.persister = original.persister; + this.lockMode = original.lockMode; + this.fetchOwnerDelegate = original.fetchOwnerDelegate; } public EntityType getAssociationType() { @@ -94,45 +96,16 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit return identifierDescription; } + @Override + public LockMode getLockMode() { + return lockMode; + } + @Override public EntityPersister retrieveFetchSourcePersister() { return persister; } - - @Override - public CollectionFetch buildCollectionFetch( - AssociationAttributeDefinition attributeDefinition, - FetchStrategy fetchStrategy, - LoadPlanBuildingContext loadPlanBuildingContext) { - return LoadPlanBuildingHelper.buildStandardCollectionFetch( - this, - attributeDefinition, - fetchStrategy, - loadPlanBuildingContext - ); - } - - @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 injectIdentifierDescription(IdentifierDescription identifierDescription) { this.identifierDescription = identifierDescription; @@ -268,4 +241,9 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit copyContext.getReturnGraphVisitationStrategy().finishingEntityFetch( this ); return copy; } + + @Override + protected FetchOwnerDelegate getFetchOwnerDelegate() { + return fetchOwnerDelegate; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/EntityFetchOwnerDelegate.java b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/EntityFetchOwnerDelegate.java new file mode 100644 index 0000000000..7ef801df07 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/EntityFetchOwnerDelegate.java @@ -0,0 +1,72 @@ +/* + * 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.loader.plan.spi; + +import org.hibernate.engine.internal.JoinHelper; +import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.persister.entity.OuterJoinLoadable; +import org.hibernate.type.AssociationType; +import org.hibernate.type.Type; + +/** + * @author Gail Badner + */ +public class EntityFetchOwnerDelegate implements FetchOwnerDelegate { + private final EntityPersister entityPersister; + + public EntityFetchOwnerDelegate(EntityPersister entityPersister) { + this.entityPersister = entityPersister; + } + + @Override + public boolean isNullable(Fetch fetch) { + return entityPersister.getPropertyNullability()[ determinePropertyIndex( fetch ) ]; + } + + @Override + public Type getType(Fetch fetch) { + return entityPersister.getPropertyTypes()[ determinePropertyIndex( fetch ) ]; + } + + @Override + public String[] getColumnNames(Fetch fetch) { + final OuterJoinLoadable outerJoinLoadable = (OuterJoinLoadable) entityPersister; + Type fetchType = getType( fetch ); + if ( fetchType.isAssociationType() ) { + return JoinHelper.getLHSColumnNames( + (AssociationType) fetchType, + determinePropertyIndex( fetch ), + outerJoinLoadable, + outerJoinLoadable.getFactory() + ); + } + else { + return outerJoinLoadable.getPropertyColumnNames( determinePropertyIndex( fetch ) ); + } + } + + private int determinePropertyIndex(Fetch fetch) { + return entityPersister.getEntityMetamodel().getPropertyIndex( fetch.getOwnerPropertyName() ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/EntityIndexGraph.java b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/EntityIndexGraph.java index ed12d31a99..384b8e98d4 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/EntityIndexGraph.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/EntityIndexGraph.java @@ -23,33 +23,24 @@ */ package org.hibernate.loader.plan.spi; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - import org.hibernate.LockMode; import org.hibernate.engine.FetchStrategy; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.loader.PropertyPath; -import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper; -import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; -import org.hibernate.persister.walking.spi.AssociationAttributeDefinition; -import org.hibernate.persister.walking.spi.CompositionDefinition; import org.hibernate.type.AssociationType; /** * @author Steve Ebersole */ -public class EntityIndexGraph extends AbstractPlanNode implements FetchableCollectionIndex, EntityReference { +public class EntityIndexGraph extends AbstractFetchOwner implements FetchableCollectionIndex, EntityReference { private final CollectionReference collectionReference; private final CollectionPersister collectionPersister; private final AssociationType indexType; private final EntityPersister indexPersister; private final PropertyPath propertyPath; - - private List fetches; + private final FetchOwnerDelegate fetchOwnerDelegate; private IdentifierDescription identifierDescription; @@ -63,28 +54,17 @@ public class EntityIndexGraph extends AbstractPlanNode implements FetchableColle this.indexType = (AssociationType) collectionPersister.getIndexType(); this.indexPersister = (EntityPersister) this.indexType.getAssociatedJoinable( sessionFactory() ); this.propertyPath = collectionPath.append( "" ); // todo : do we want the part? + this.fetchOwnerDelegate = new EntityFetchOwnerDelegate( indexPersister ); } public EntityIndexGraph(EntityIndexGraph original, CopyContext copyContext) { - super( original ); + super( original, copyContext ); this.collectionReference = original.collectionReference; this.collectionPersister = original.collectionReference.getCollectionPersister(); this.indexType = original.indexType; this.indexPersister = original.indexPersister; this.propertyPath = original.propertyPath; - - copyContext.getReturnGraphVisitationStrategy().startingFetches( original ); - if ( fetches == null || fetches.size() == 0 ) { - this.fetches = Collections.emptyList(); - } - else { - List fetchesCopy = new ArrayList(); - for ( Fetch fetch : fetches ) { - fetchesCopy.add( fetch.makeCopy( copyContext, this ) ); - } - this.fetches = fetchesCopy; - } - copyContext.getReturnGraphVisitationStrategy().finishingFetches( original ); + this.fetchOwnerDelegate = original.fetchOwnerDelegate; } @Override @@ -107,19 +87,6 @@ public class EntityIndexGraph extends AbstractPlanNode implements FetchableColle return identifierDescription; } - @Override - public void addFetch(Fetch fetch) { - if ( fetches == null ) { - fetches = new ArrayList(); - } - fetches.add( fetch ); - } - - @Override - public Fetch[] getFetches() { - return fetches == null ? NO_FETCHES : fetches.toArray( new Fetch[ fetches.size() ] ); - } - @Override public void validateFetchPlan(FetchStrategy fetchStrategy) { } @@ -134,39 +101,6 @@ public class EntityIndexGraph extends AbstractPlanNode implements FetchableColle return propertyPath; } - @Override - public CollectionFetch buildCollectionFetch( - AssociationAttributeDefinition attributeDefinition, - FetchStrategy fetchStrategy, - LoadPlanBuildingContext loadPlanBuildingContext) { - return LoadPlanBuildingHelper.buildStandardCollectionFetch( - this, - attributeDefinition, - fetchStrategy, - loadPlanBuildingContext - ); - } - - @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 injectIdentifierDescription(IdentifierDescription identifierDescription) { this.identifierDescription = identifierDescription; @@ -176,4 +110,9 @@ public class EntityIndexGraph extends AbstractPlanNode implements FetchableColle public EntityIndexGraph makeCopy(CopyContext copyContext) { return new EntityIndexGraph( this, copyContext ); } + + @Override + protected FetchOwnerDelegate getFetchOwnerDelegate() { + return fetchOwnerDelegate; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/EntityReturn.java b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/EntityReturn.java index cb15874c8b..7680e4a30f 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/EntityReturn.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/EntityReturn.java @@ -32,12 +32,8 @@ import org.hibernate.engine.FetchStrategy; import org.hibernate.engine.spi.EntityKey; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.loader.PropertyPath; -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 static org.hibernate.loader.spi.ResultSetProcessingContext.IdentifierResolutionContext; @@ -50,24 +46,32 @@ public class EntityReturn extends AbstractFetchOwner implements Return, EntityRe private final PropertyPath propertyPath = new PropertyPath(); // its a root + private final LockMode lockMode; + + private final FetchOwnerDelegate fetchOwnerDelegate; + private IdentifierDescription identifierDescription; public EntityReturn( SessionFactoryImplementor sessionFactory, LockMode lockMode, String entityName) { - super( sessionFactory, lockMode ); - + super( sessionFactory ); this.persister = sessionFactory.getEntityPersister( entityName ); + this.lockMode = lockMode; + this.fetchOwnerDelegate = new EntityFetchOwnerDelegate( persister ); } protected EntityReturn(EntityReturn original, CopyContext copyContext) { super( original, copyContext ); this.persister = original.persister; + this.lockMode = original.lockMode; + this.fetchOwnerDelegate = original.fetchOwnerDelegate; } + @Override public LockMode getLockMode() { - return super.getLockMode(); + return lockMode; } @Override @@ -99,39 +103,6 @@ public class EntityReturn extends AbstractFetchOwner implements Return, EntityRe return propertyPath; } - @Override - public CollectionFetch buildCollectionFetch( - AssociationAttributeDefinition attributeDefinition, - FetchStrategy fetchStrategy, - LoadPlanBuildingContext loadPlanBuildingContext) { - return LoadPlanBuildingHelper.buildStandardCollectionFetch( - this, - attributeDefinition, - fetchStrategy, - loadPlanBuildingContext - ); - } - - @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 { EntityKey entityKey = getEntityKeyFromContext( context ); @@ -207,4 +178,9 @@ public class EntityReturn extends AbstractFetchOwner implements Return, EntityRe public EntityReturn makeCopy(CopyContext copyContext) { return new EntityReturn( this, copyContext ); } + + @Override + protected FetchOwnerDelegate getFetchOwnerDelegate() { + return fetchOwnerDelegate; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/Fetch.java b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/Fetch.java index ab344a17f2..9d34ff51ad 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/Fetch.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/Fetch.java @@ -52,6 +52,10 @@ public interface Fetch extends CopyableFetch { */ public String getOwnerPropertyName(); + public boolean isNullable(); + + public String[] getColumnNames(); + public FetchStrategy getFetchStrategy(); /** diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/FetchOwner.java b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/FetchOwner.java index 102180bdb1..9558e987d3 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/FetchOwner.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/FetchOwner.java @@ -29,6 +29,7 @@ import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.walking.spi.AssociationAttributeDefinition; import org.hibernate.persister.walking.spi.CompositionDefinition; +import org.hibernate.type.Type; /** * Contract for owners of fetches. Any non-scalar return could be a fetch owner. @@ -56,6 +57,12 @@ public interface FetchOwner { */ public Fetch[] getFetches(); + public Type getType(Fetch fetch); + + public boolean isNullable(Fetch fetch); + + public String[] getColumnNames(Fetch fetch); + /** * Is the asserted plan valid from this owner to a fetch? * diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/FetchOwnerDelegate.java b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/FetchOwnerDelegate.java new file mode 100644 index 0000000000..523891b3ef --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/FetchOwnerDelegate.java @@ -0,0 +1,38 @@ +/* + * 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.loader.plan.spi; + +import org.hibernate.type.Type; + +/** + * @author Gail Badner + */ +public interface FetchOwnerDelegate { + + public boolean isNullable(Fetch fetch); + + public Type getType(Fetch fetch); + + public String[] getColumnNames(Fetch fetch); +} \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/FetchableCollectionElement.java b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/FetchableCollectionElement.java index 5b18a01029..c4f090f9e5 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/FetchableCollectionElement.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/FetchableCollectionElement.java @@ -23,10 +23,14 @@ */ package org.hibernate.loader.plan.spi; +import org.hibernate.persister.collection.CollectionPersister; + /** * @author Steve Ebersole */ public interface FetchableCollectionElement extends FetchOwner, CopyableReturn { @Override public FetchableCollectionElement makeCopy(CopyContext copyContext); + + public CollectionReference getCollectionReference(); } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/build/AbstractLoadPlanBuilderStrategy.java b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/build/AbstractLoadPlanBuilderStrategy.java index a15dd2a877..d7c12c762d 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/build/AbstractLoadPlanBuilderStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/build/AbstractLoadPlanBuilderStrategy.java @@ -49,16 +49,20 @@ import org.hibernate.loader.plan.spi.AbstractSingularAttributeFetch; import org.hibernate.loader.plan.spi.CollectionFetch; import org.hibernate.loader.plan.spi.CollectionReference; import org.hibernate.loader.plan.spi.CollectionReturn; +import org.hibernate.loader.plan.spi.CompositeElementGraph; import org.hibernate.loader.plan.spi.CompositeFetch; +import org.hibernate.loader.plan.spi.CompositeFetchOwnerDelegate; import org.hibernate.loader.plan.spi.EntityFetch; import org.hibernate.loader.plan.spi.EntityReference; import org.hibernate.loader.plan.spi.EntityReturn; import org.hibernate.loader.plan.spi.Fetch; import org.hibernate.loader.plan.spi.FetchOwner; +import org.hibernate.loader.plan.spi.FetchOwnerDelegate; import org.hibernate.loader.plan.spi.IdentifierDescription; import org.hibernate.loader.plan.spi.Return; import org.hibernate.loader.spi.ResultSetProcessingContext; import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.persister.entity.Loadable; import org.hibernate.persister.spi.HydratedCompoundValueHandler; import org.hibernate.persister.walking.spi.AssociationAttributeDefinition; import org.hibernate.persister.walking.spi.AttributeDefinition; @@ -66,9 +70,11 @@ 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.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; +import org.hibernate.type.CompositeType; import org.hibernate.type.Type; import static org.hibernate.loader.spi.ResultSetProcessingContext.IdentifierResolutionContext; @@ -192,7 +198,12 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder final FetchOwner identifierAttributeCollector; if ( entityIdentifierDefinition.isEncapsulated() ) { - identifierAttributeCollector = new EncapsulatedIdentifierAttributeCollector( entityReference ); + if ( entityIdentifierDefinition.getEntityDefinition().getEntityPersister().getIdentifierType().isComponentType() ) { + identifierAttributeCollector = new EncapsulatedCompositeIdentifierAttributeCollector( entityReference ); + } + else { + identifierAttributeCollector = new EncapsulatedIdentifierAttributeCollector( entityReference ); + } } else { identifierAttributeCollector = new NonEncapsulatedIdentifierAttributeCollector( entityReference ); @@ -307,6 +318,35 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder // - the element graph pushed while starting would be popped in finishing/Entity/finishingComposite } + @Override + public void startingCompositeElement(CompositionElementDefinition compositeElementDefinition) { + System.out.println( + String.format( + "%s Starting composite collection element for (%s)", + StringHelper.repeat( ">>", fetchOwnerStack.size() ), + compositeElementDefinition.getCollectionDefinition().getCollectionPersister().getRole() + ) + ); + } + + @Override + public void finishingCompositeElement(CompositionElementDefinition 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) { // pop the current fetch owner, and make sure what we just popped represents this collection @@ -513,6 +553,11 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder return entityReference.getEntityPersister(); } + @Override + public boolean isNullable(Fetch fetch) { + return false; + } + @Override public IdentifierDescription getIdentifierDescription() { return entityReference.getIdentifierDescription(); @@ -596,6 +641,13 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder } } + protected static abstract class AbstractCompositeIdentifierAttributeCollector extends AbstractIdentifierAttributeCollector { + + public AbstractCompositeIdentifierAttributeCollector(EntityReference entityReference) { + super( entityReference ); + } + } + protected static class EncapsulatedIdentifierAttributeCollector extends AbstractIdentifierAttributeCollector { private final PropertyPath propertyPath; @@ -613,17 +665,76 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder ); } + @Override + public Type getType(Fetch fetch) { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public String[] getColumnNames(Fetch fetch) { + return ( (Loadable) entityReference.getEntityPersister() ).getIdentifierColumnNames(); + } + @Override public PropertyPath getPropertyPath() { return propertyPath; } } - protected static class NonEncapsulatedIdentifierAttributeCollector extends AbstractIdentifierAttributeCollector { + protected static class EncapsulatedCompositeIdentifierAttributeCollector extends AbstractCompositeIdentifierAttributeCollector { private final PropertyPath propertyPath; + + public EncapsulatedCompositeIdentifierAttributeCollector(EntityReference entityReference) { + super( entityReference ); + this.propertyPath = ( (FetchOwner) entityReference ).getPropertyPath(); + } + + @Override + protected IdentifierDescription buildIdentifierDescription() { + return new IdentifierDescriptionImpl( + entityReference, + identifierFetches.toArray( new AbstractSingularAttributeFetch[ identifierFetches.size() ] ), + null + ); + } + + @Override + public PropertyPath getPropertyPath() { + return propertyPath; + } + + @Override + public Type getType(Fetch fetch) { + if ( !fetch.getOwnerPropertyName().equals( entityReference.getEntityPersister().getIdentifierPropertyName() ) ) { + throw new IllegalArgumentException( + String.format( + "Fetch owner property name [%s] is not the same as the identifier property name [%s].", + fetch.getOwnerPropertyName(), + entityReference.getEntityPersister().getIdentifierPropertyName() + ) + ); + } + return entityReference.getEntityPersister().getIdentifierType(); + } + + @Override + public String[] getColumnNames(Fetch fetch) { + return ( (Loadable) entityReference.getEntityPersister() ).getIdentifierColumnNames(); + } + } + + protected static class NonEncapsulatedIdentifierAttributeCollector extends AbstractCompositeIdentifierAttributeCollector { + private final PropertyPath propertyPath; + private final FetchOwnerDelegate fetchOwnerDelegate; + public NonEncapsulatedIdentifierAttributeCollector(EntityReference entityReference) { super( entityReference ); this.propertyPath = ( (FetchOwner) entityReference ).getPropertyPath().append( "" ); + this.fetchOwnerDelegate = new CompositeFetchOwnerDelegate( + entityReference.getEntityPersister().getFactory(), + (CompositeType) entityReference.getEntityPersister().getIdentifierType(), + ( (Loadable) entityReference.getEntityPersister() ).getIdentifierColumnNames() + ); } @Override @@ -639,6 +750,24 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder public PropertyPath getPropertyPath() { return propertyPath; } + + + public Type getType(Fetch fetch) { + if ( !fetch.getOwnerPropertyName().equals( entityReference.getEntityPersister().getIdentifierPropertyName() ) ) { + throw new IllegalArgumentException( + String.format( + "Fetch owner property name [%s] is not the same as the identifier property name [%s].", + fetch.getOwnerPropertyName(), + entityReference.getEntityPersister().getIdentifierPropertyName() + ) + ); + } + return fetchOwnerDelegate.getType( fetch ); + } + + public String[] getColumnNames(Fetch fetch) { + return fetchOwnerDelegate.getColumnNames( fetch ); + } } private static class IdentifierDescriptionImpl implements IdentifierDescription { diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java index 819ad1b0a4..aa1831b121 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java @@ -80,10 +80,14 @@ import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.Loadable; import org.hibernate.persister.entity.PropertyMapping; import org.hibernate.persister.entity.Queryable; +import org.hibernate.persister.walking.internal.CompositionSingularSubAttributesHelper; +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.CollectionElementDefinition; import org.hibernate.persister.walking.spi.CollectionIndexDefinition; 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; @@ -1941,7 +1945,6 @@ public abstract class AbstractCollectionPersister public abstract FilterAliasGenerator getFilterAliasGenerator(final String rootAlias); - // ColectionDefinition impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @Override @@ -2007,12 +2010,42 @@ public abstract class AbstractCollectionPersister } @Override - public CompositionDefinition toCompositeDefinition() { + public CompositionElementDefinition toCompositeElementDefinition() { + final String propertyName = role.substring( entityName.length() + 1 ); + final int propertyIndex = ownerPersister.getEntityMetamodel().getPropertyIndex( propertyName ); + if ( ! getType().isComponentType() ) { throw new IllegalStateException( "Cannot treat entity collection element type as composite" ); } - // todo : implement - throw new NotYetImplementedException(); + + return new CompositionElementDefinition() { + @Override + public String getName() { + return ""; + } + + @Override + public Type getType() { + return getElementType(); + } + + @Override + public AttributeSource getSource() { + // TODO: what if this is a collection w/in an encapsulated composition attribute? + // should return the encapsulated composition attribute instead??? + return getOwnerEntityPersister(); + } + + @Override + public Iterable getAttributes() { + return CompositionSingularSubAttributesHelper.getCompositionElementSubAttributes( this ); + } + + @Override + public CollectionDefinition getCollectionDefinition() { + return AbstractCollectionPersister.this; + } + }; } }; } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java index 51062e1524..9552291f79 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java @@ -59,7 +59,6 @@ import org.hibernate.cache.spi.entry.ReferenceCacheEntryImpl; import org.hibernate.cache.spi.entry.StandardCacheEntryImpl; import org.hibernate.cache.spi.entry.StructuredCacheEntry; import org.hibernate.cache.spi.entry.UnstructuredCacheEntry; -import org.hibernate.cfg.NotYetImplementedException; import org.hibernate.dialect.lock.LockingStrategy; import org.hibernate.engine.OptimisticLockStyle; import org.hibernate.engine.internal.StatefulPersistenceContext; @@ -111,12 +110,7 @@ import org.hibernate.metamodel.relational.DerivedValue; import org.hibernate.metamodel.relational.Value; import org.hibernate.persister.walking.internal.EntityIdentifierDefinitionHelper; import org.hibernate.persister.walking.spi.AttributeDefinition; -import org.hibernate.persister.walking.spi.AttributeSource; -import org.hibernate.persister.walking.spi.CompositionDefinition; -import org.hibernate.persister.walking.spi.EncapsulatedEntityIdentifierDefinition; -import org.hibernate.persister.walking.spi.EntityDefinition; import org.hibernate.persister.walking.spi.EntityIdentifierDefinition; -import org.hibernate.persister.walking.spi.NonEncapsulatedEntityIdentifierDefinition; import org.hibernate.pretty.MessageHelper; import org.hibernate.property.BackrefPropertyAccessor; import org.hibernate.sql.Alias; @@ -132,7 +126,6 @@ import org.hibernate.sql.Update; import org.hibernate.tuple.entity.EntityMetamodel; import org.hibernate.tuple.entity.EntityTuplizer; import org.hibernate.type.AssociationType; -import org.hibernate.type.ComponentType; import org.hibernate.type.CompositeType; import org.hibernate.type.EntityType; import org.hibernate.type.Type; diff --git a/hibernate-core/src/main/java/org/hibernate/persister/walking/internal/CompositionSingularSubAttributesHelper.java b/hibernate-core/src/main/java/org/hibernate/persister/walking/internal/CompositionSingularSubAttributesHelper.java new file mode 100644 index 0000000000..8cac9860c0 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/persister/walking/internal/CompositionSingularSubAttributesHelper.java @@ -0,0 +1,212 @@ +package org.hibernate.persister.walking.internal; + +import java.util.Iterator; + +import org.hibernate.engine.FetchStrategy; +import org.hibernate.engine.FetchStyle; +import org.hibernate.engine.FetchTiming; +import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.engine.spi.CascadeStyles; +import org.hibernate.engine.spi.LoadQueryInfluencers; +import org.hibernate.internal.util.collections.ArrayHelper; +import org.hibernate.loader.PropertyPath; +import org.hibernate.persister.collection.QueryableCollection; +import org.hibernate.persister.entity.AbstractEntityPersister; +import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.persister.entity.OuterJoinLoadable; +import org.hibernate.persister.spi.HydratedCompoundValueHandler; +import org.hibernate.persister.walking.spi.AssociationAttributeDefinition; +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.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; +import org.hibernate.type.CompositeType; +import org.hibernate.type.Type; + +/** + * @author Gail Badner + */ +public class CompositionSingularSubAttributesHelper { + + public static Iterable getIdentifierSubAttributes( + final AbstractEntityPersister entityPersister) { + return getSingularSubAttributes( + entityPersister, + entityPersister, + (CompositeType) entityPersister.getIdentifierType(), + entityPersister.getTableName(), + entityPersister.getRootTableIdentifierColumnNames() + ); + } + + public static Iterable getCompositionElementSubAttributes( + CompositionElementDefinition compositionElementDefinition) { + final QueryableCollection collectionPersister = + (QueryableCollection) compositionElementDefinition.getCollectionDefinition().getCollectionPersister(); + return getSingularSubAttributes( + compositionElementDefinition.getSource(), + (OuterJoinLoadable) collectionPersister.getOwnerEntityPersister(), + (CompositeType) collectionPersister.getElementType(), + collectionPersister.getTableName(), + collectionPersister.getElementColumnNames() + ); + } + + private static Iterable getSingularSubAttributes( + final AttributeSource source, + final OuterJoinLoadable ownerEntityPersister, + final CompositeType compositeType, + final String lhsTableName, + final String[] lhsColumns) { + return new Iterable() { + @Override + public Iterator iterator() { + return new Iterator() { + private final int numberOfAttributes = compositeType.getSubtypes().length; + private int currentSubAttributeNumber = 0; + private int currentColumnPosition = 0; + + @Override + public boolean hasNext() { + return currentSubAttributeNumber < numberOfAttributes; + } + + @Override + public AttributeDefinition next() { + final int subAttributeNumber = currentSubAttributeNumber; + currentSubAttributeNumber++; + + final String name = compositeType.getPropertyNames()[subAttributeNumber]; + final Type type = compositeType.getSubtypes()[subAttributeNumber]; + + final int columnPosition = currentColumnPosition; + final int columnSpan = type.getColumnSpan( ownerEntityPersister.getFactory() ); + final String[] subAttributeLhsColumns = ArrayHelper.slice( lhsColumns, columnPosition, columnSpan ); + + currentColumnPosition += columnSpan; + + if ( type.isAssociationType() ) { + final AssociationType aType = (AssociationType) type; + return new AssociationAttributeDefinition() { + @Override + public AssociationKey getAssociationKey() { + /* TODO: is this always correct? */ + //return new AssociationKey( + // joinable.getTableName(), + // JoinHelper.getRHSColumnNames( aType, getEntityPersister().getFactory() ) + //); + return new AssociationKey( + lhsTableName, + subAttributeLhsColumns + ); + } + + @Override + public boolean isCollection() { + return false; + } + + @Override + public EntityDefinition toEntityDefinition() { + return (EntityPersister) aType.getAssociatedJoinable( ownerEntityPersister.getFactory() ); + } + + @Override + public CollectionDefinition toCollectionDefinition() { + throw new WalkingException( "A collection cannot be mapped to a composite ID sub-attribute." ); + } + + @Override + public FetchStrategy determineFetchPlan(LoadQueryInfluencers loadQueryInfluencers, PropertyPath propertyPath) { + return new FetchStrategy( FetchTiming.IMMEDIATE, FetchStyle.JOIN ); + } + + @Override + public CascadeStyle determineCascadeStyle() { + return CascadeStyles.NONE; + } + + @Override + public HydratedCompoundValueHandler getHydratedCompoundValueExtractor() { + return null; + } + + @Override + public String getName() { + return name; + } + + @Override + public Type getType() { + return type; + } + + @Override + public AttributeSource getSource() { + return source; + } + }; + } + else if ( type.isComponentType() ) { + return new CompositionDefinition() { + @Override + public String getName() { + return name; + } + + @Override + public Type getType() { + return type; + } + + @Override + public AttributeSource getSource() { + return this; + } + + @Override + public Iterable getAttributes() { + return CompositionSingularSubAttributesHelper.getSingularSubAttributes( + this, + ownerEntityPersister, + (CompositeType) type, + lhsTableName, + subAttributeLhsColumns + ); + } + }; + } + else { + return new AttributeDefinition() { + @Override + public String getName() { + return name; + } + + @Override + public Type getType() { + return type; + } + + @Override + public AttributeSource getSource() { + return source; + } + }; + } + } + + @Override + public void remove() { + throw new UnsupportedOperationException( "Remove operation not supported here" ); + } + }; + } + }; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/persister/walking/internal/EntityIdentifierDefinitionHelper.java b/hibernate-core/src/main/java/org/hibernate/persister/walking/internal/EntityIdentifierDefinitionHelper.java index abb5e5b958..bec4320dc2 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/walking/internal/EntityIdentifierDefinitionHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/walking/internal/EntityIdentifierDefinitionHelper.java @@ -23,37 +23,16 @@ */ package org.hibernate.persister.walking.internal; -import java.util.Iterator; - -import org.hibernate.engine.FetchStrategy; -import org.hibernate.engine.FetchStyle; -import org.hibernate.engine.FetchTiming; -import org.hibernate.engine.spi.CascadeStyle; -import org.hibernate.engine.spi.CascadeStyles; -import org.hibernate.engine.spi.LoadQueryInfluencers; -import org.hibernate.loader.PropertyPath; import org.hibernate.persister.entity.AbstractEntityPersister; -import org.hibernate.persister.entity.EntityPersister; -import org.hibernate.persister.entity.Joinable; -import org.hibernate.persister.spi.HydratedCompoundValueHandler; -import org.hibernate.persister.walking.spi.AssociationAttributeDefinition; -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.CompositionDefinition; import org.hibernate.persister.walking.spi.EncapsulatedEntityIdentifierDefinition; import org.hibernate.persister.walking.spi.EntityDefinition; import org.hibernate.persister.walking.spi.EntityIdentifierDefinition; import org.hibernate.persister.walking.spi.NonEncapsulatedEntityIdentifierDefinition; -import org.hibernate.persister.walking.spi.WalkingException; -import org.hibernate.type.AssociationType; -import org.hibernate.type.ComponentType; import org.hibernate.type.Type; -import static org.hibernate.engine.internal.JoinHelper.getLHSColumnNames; -import static org.hibernate.engine.internal.JoinHelper.getLHSTableName; - /** * @author Gail Badner */ @@ -78,12 +57,13 @@ public class EntityIdentifierDefinitionHelper { }; } - public static EntityIdentifierDefinition buildEncapsulatedCompositeIdentifierDefinition(final AbstractEntityPersister entityPersister) { + public static EntityIdentifierDefinition buildEncapsulatedCompositeIdentifierDefinition( + final AbstractEntityPersister entityPersister) { return new EncapsulatedEntityIdentifierDefinition() { @Override public AttributeDefinition getAttributeDefinition() { - return new CompositeAttributeDefinitionAdapter( entityPersister ); + return new CompositionDefinitionAdapter( entityPersister ); } @Override @@ -102,7 +82,7 @@ public class EntityIdentifierDefinitionHelper { return new NonEncapsulatedEntityIdentifierDefinition() { @Override public Iterable getAttributes() { - return new CompositeAttributeDefinitionAdapter( entityPersister ).getAttributes(); + return CompositionSingularSubAttributesHelper.getIdentifierSubAttributes( entityPersister ); } @Override @@ -154,160 +134,20 @@ public class EntityIdentifierDefinitionHelper { } } - private static class CompositeAttributeDefinitionAdapter extends AttributeDefinitionAdapter implements CompositionDefinition { + private static class CompositionDefinitionAdapter extends AttributeDefinitionAdapter implements CompositionDefinition { - CompositeAttributeDefinitionAdapter(AbstractEntityPersister entityPersister) { + CompositionDefinitionAdapter(AbstractEntityPersister entityPersister) { super( entityPersister ); } + @Override + public String toString() { + return ""; + } + @Override public Iterable getAttributes() { - return new Iterable() { - @Override - public Iterator iterator() { - final ComponentType componentType = (ComponentType) getType(); - return new Iterator() { - private final int numberOfAttributes = componentType.getSubtypes().length; - private int currentSubAttributeNumber = 0; - private int currentColumnPosition = 0; - - @Override - public boolean hasNext() { - return currentSubAttributeNumber < numberOfAttributes; - } - - @Override - public AttributeDefinition next() { - final int subAttributeNumber = currentSubAttributeNumber; - currentSubAttributeNumber++; - - final AttributeSource source = getSource(); - final String name = componentType.getPropertyNames()[subAttributeNumber]; - final Type type = componentType.getSubtypes()[subAttributeNumber]; - - final int columnPosition = currentColumnPosition; - currentColumnPosition += type.getColumnSpan( getEntityPersister().getFactory() ); - - if ( type.isAssociationType() ) { - final AssociationType aType = (AssociationType) type; - final Joinable joinable = aType.getAssociatedJoinable( getEntityPersister().getFactory() ); - return new AssociationAttributeDefinition() { - @Override - public AssociationKey getAssociationKey() { - /* TODO: is this always correct? */ - //return new AssociationKey( - // joinable.getTableName(), - // JoinHelper.getRHSColumnNames( aType, getEntityPersister().getFactory() ) - //); - return new AssociationKey( - getEntityPersister().getTableName(), - getLHSColumnNames( - aType, - -1, - columnPosition, - getEntityPersister(), - getEntityPersister().getFactory() - ) - ); - - } - - @Override - public boolean isCollection() { - return false; - } - - @Override - public EntityDefinition toEntityDefinition() { - return (EntityPersister) joinable; - } - - @Override - public CollectionDefinition toCollectionDefinition() { - throw new WalkingException( "A collection cannot be mapped to a composite ID sub-attribute." ); - } - - @Override - public FetchStrategy determineFetchPlan(LoadQueryInfluencers loadQueryInfluencers, PropertyPath propertyPath) { - return new FetchStrategy( FetchTiming.IMMEDIATE, FetchStyle.JOIN ); - } - - @Override - public CascadeStyle determineCascadeStyle() { - return CascadeStyles.NONE; - } - - @Override - public HydratedCompoundValueHandler getHydratedCompoundValueExtractor() { - return null; - } - - @Override - public String getName() { - return name; - } - - @Override - public Type getType() { - return type; - } - - @Override - public AttributeSource getSource() { - return source; - } - }; - } - else if ( type.isComponentType() ) { - return new CompositionDefinition() { - @Override - public String getName() { - return name; - } - - @Override - public Type getType() { - return type; - } - - @Override - public AttributeSource getSource() { - return source; - } - - @Override - public Iterable getAttributes() { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - }; - } - else { - return new AttributeDefinition() { - @Override - public String getName() { - return name; - } - - @Override - public Type getType() { - return type; - } - - @Override - public AttributeSource getSource() { - return source; - } - }; - } - } - - @Override - public void remove() { - throw new UnsupportedOperationException( "Remove operation not supported here" ); - } - }; - } - }; + return CompositionSingularSubAttributesHelper.getIdentifierSubAttributes( getEntityPersister() ); } } } \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/persister/walking/spi/AssociationVisitationStrategy.java b/hibernate-core/src/main/java/org/hibernate/persister/walking/spi/AssociationVisitationStrategy.java index 285ec22270..6bf7d9a156 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/walking/spi/AssociationVisitationStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/walking/spi/AssociationVisitationStrategy.java @@ -55,6 +55,9 @@ public interface AssociationVisitationStrategy { public void startingComposite(CompositionDefinition compositionDefinition); public void finishingComposite(CompositionDefinition compositionDefinition); + public void startingCompositeElement(CompositionElementDefinition compositionElementDefinition); + public void finishingCompositeElement(CompositionElementDefinition compositionElementDefinition); + public boolean startingAttribute(AttributeDefinition attributeDefinition); public void finishingAttribute(AttributeDefinition attributeDefinition); } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/walking/spi/CollectionElementDefinition.java b/hibernate-core/src/main/java/org/hibernate/persister/walking/spi/CollectionElementDefinition.java index b42f8b0ddc..ff138f76f4 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/walking/spi/CollectionElementDefinition.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/walking/spi/CollectionElementDefinition.java @@ -35,5 +35,5 @@ public interface CollectionElementDefinition { public EntityDefinition toEntityDefinition(); - public CompositionDefinition toCompositeDefinition(); + public CompositionElementDefinition toCompositeElementDefinition(); } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/walking/spi/CompositionElementDefinition.java b/hibernate-core/src/main/java/org/hibernate/persister/walking/spi/CompositionElementDefinition.java new file mode 100644 index 0000000000..cd073881c8 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/persister/walking/spi/CompositionElementDefinition.java @@ -0,0 +1,31 @@ +/* + * 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.spi; + +/** + * @author Gail Badner + */ +public interface CompositionElementDefinition extends CompositionDefinition{ + public CollectionDefinition getCollectionDefinition(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/persister/walking/spi/MetadataDrivenModelGraphVisitor.java b/hibernate-core/src/main/java/org/hibernate/persister/walking/spi/MetadataDrivenModelGraphVisitor.java index 3b5caa44ae..ffdccb2b99 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/walking/spi/MetadataDrivenModelGraphVisitor.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/walking/spi/MetadataDrivenModelGraphVisitor.java @@ -28,21 +28,12 @@ import java.util.Set; import org.jboss.logging.Logger; -import org.hibernate.engine.FetchStrategy; -import org.hibernate.engine.FetchStyle; -import org.hibernate.engine.FetchTiming; -import org.hibernate.engine.spi.CascadeStyle; -import org.hibernate.engine.spi.LoadQueryInfluencers; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.loader.PropertyPath; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; -import org.hibernate.persister.entity.Joinable; -import org.hibernate.persister.spi.HydratedCompoundValueHandler; import org.hibernate.type.Type; -import static org.hibernate.engine.internal.JoinHelper.getRHSColumnNames; - /** * Provides model graph visitation based on the defined metadata (as opposed to based on the incoming graph * as we see in cascade processing). In layman terms, we are walking the graph of the users model as defined by @@ -211,7 +202,7 @@ public class MetadataDrivenModelGraphVisitor { strategy.startingCollectionElements( elementDefinition ); if ( elementDefinition.getType().isComponentType() ) { - visitCompositeDefinition( elementDefinition.toCompositeDefinition() ); + visitCompositeElementDefinition( elementDefinition.toCompositeElementDefinition() ); } else if ( elementDefinition.getType().isEntityType() ) { visitEntityDefinition( elementDefinition.toEntityDefinition() ); @@ -220,6 +211,13 @@ public class MetadataDrivenModelGraphVisitor { strategy.finishingCollectionElements( elementDefinition ); } + private void visitCompositeElementDefinition(CompositionElementDefinition compositionElementDefinition) { + strategy.startingCompositeElement( compositionElementDefinition ); + + visitAttributes( compositionElementDefinition ); + + strategy.finishingCompositeElement( compositionElementDefinition ); + } private final Set visitedAssociationKeys = new HashSet(); diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractCompositeBasedAttribute.java b/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractCompositeBasedAttribute.java index a225b8a05f..9dbcbc7558 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractCompositeBasedAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractCompositeBasedAttribute.java @@ -39,7 +39,7 @@ public abstract class AbstractCompositeBasedAttribute private final int ownerAttributeNumber; public AbstractCompositeBasedAttribute( - AbstractCompositionDefinition source, + AbstractCompositionAttribute source, SessionFactoryImplementor sessionFactory, int attributeNumber, String attributeName, @@ -55,7 +55,7 @@ public abstract class AbstractCompositeBasedAttribute } @Override - public AbstractCompositionDefinition getSource() { - return (AbstractCompositionDefinition) super.getSource(); + public AbstractCompositionAttribute getSource() { + return (AbstractCompositionAttribute) super.getSource(); } } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractCompositionDefinition.java b/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractCompositionAttribute.java similarity index 79% rename from hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractCompositionDefinition.java rename to hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractCompositionAttribute.java index 554a630ed6..e563a9dd9e 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractCompositionDefinition.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractCompositionAttribute.java @@ -48,9 +48,9 @@ import static org.hibernate.engine.internal.JoinHelper.getRHSColumnNames; /** * @author Steve Ebersole */ -public abstract class AbstractCompositionDefinition extends AbstractNonIdentifierAttribute implements +public abstract class AbstractCompositionAttribute extends AbstractNonIdentifierAttribute implements CompositionDefinition { - protected AbstractCompositionDefinition( + protected AbstractCompositionAttribute( AttributeSource source, SessionFactoryImplementor sessionFactory, int attributeNumber, @@ -120,41 +120,41 @@ public abstract class AbstractCompositionDefinition extends AbstractNonIdentifie } return new CompositeBasedAssociationAttribute( - AbstractCompositionDefinition.this, + AbstractCompositionAttribute.this, sessionFactory(), subAttributeNumber, name, (AssociationType) type, new BaselineAttributeInformation.Builder() - .setInsertable( AbstractCompositionDefinition.this.isInsertable() ) - .setUpdateable( AbstractCompositionDefinition.this.isUpdateable() ) - .setInsertGenerated( AbstractCompositionDefinition.this.isInsertGenerated() ) - .setUpdateGenerated( AbstractCompositionDefinition.this.isUpdateGenerated() ) + .setInsertable( AbstractCompositionAttribute.this.isInsertable() ) + .setUpdateable( AbstractCompositionAttribute.this.isUpdateable() ) + .setInsertGenerated( AbstractCompositionAttribute.this.isInsertGenerated() ) + .setUpdateGenerated( AbstractCompositionAttribute.this.isUpdateGenerated() ) .setNullable( getType().getPropertyNullability()[subAttributeNumber] ) .setDirtyCheckable( true ) - .setVersionable( AbstractCompositionDefinition.this.isVersionable() ) + .setVersionable( AbstractCompositionAttribute.this.isVersionable() ) .setCascadeStyle( getType().getCascadeStyle( subAttributeNumber ) ) .setFetchMode( getType().getFetchMode( subAttributeNumber ) ) .createInformation(), - AbstractCompositionDefinition.this.attributeNumber(), + AbstractCompositionAttribute.this.attributeNumber(), associationKey ); } else if ( type.isComponentType() ) { return new CompositionBasedCompositionAttribute( - AbstractCompositionDefinition.this, + AbstractCompositionAttribute.this, sessionFactory(), subAttributeNumber, name, (CompositeType) type, new BaselineAttributeInformation.Builder() - .setInsertable( AbstractCompositionDefinition.this.isInsertable() ) - .setUpdateable( AbstractCompositionDefinition.this.isUpdateable() ) - .setInsertGenerated( AbstractCompositionDefinition.this.isInsertGenerated() ) - .setUpdateGenerated( AbstractCompositionDefinition.this.isUpdateGenerated() ) + .setInsertable( AbstractCompositionAttribute.this.isInsertable() ) + .setUpdateable( AbstractCompositionAttribute.this.isUpdateable() ) + .setInsertGenerated( AbstractCompositionAttribute.this.isInsertGenerated() ) + .setUpdateGenerated( AbstractCompositionAttribute.this.isUpdateGenerated() ) .setNullable( getType().getPropertyNullability()[subAttributeNumber] ) .setDirtyCheckable( true ) - .setVersionable( AbstractCompositionDefinition.this.isVersionable() ) + .setVersionable( AbstractCompositionAttribute.this.isVersionable() ) .setCascadeStyle( getType().getCascadeStyle( subAttributeNumber ) ) .setFetchMode( getType().getFetchMode( subAttributeNumber ) ) .createInformation() @@ -162,19 +162,19 @@ public abstract class AbstractCompositionDefinition extends AbstractNonIdentifie } else { return new CompositeBasedBasicAttribute( - AbstractCompositionDefinition.this, + AbstractCompositionAttribute.this, sessionFactory(), subAttributeNumber, name, type, new BaselineAttributeInformation.Builder() - .setInsertable( AbstractCompositionDefinition.this.isInsertable() ) - .setUpdateable( AbstractCompositionDefinition.this.isUpdateable() ) - .setInsertGenerated( AbstractCompositionDefinition.this.isInsertGenerated() ) - .setUpdateGenerated( AbstractCompositionDefinition.this.isUpdateGenerated() ) + .setInsertable( AbstractCompositionAttribute.this.isInsertable() ) + .setUpdateable( AbstractCompositionAttribute.this.isUpdateable() ) + .setInsertGenerated( AbstractCompositionAttribute.this.isInsertGenerated() ) + .setUpdateGenerated( AbstractCompositionAttribute.this.isUpdateGenerated() ) .setNullable( getType().getPropertyNullability()[subAttributeNumber] ) .setDirtyCheckable( true ) - .setVersionable( AbstractCompositionDefinition.this.isVersionable() ) + .setVersionable( AbstractCompositionAttribute.this.isVersionable() ) .setCascadeStyle( getType().getCascadeStyle( subAttributeNumber ) ) .setFetchMode( getType().getFetchMode( subAttributeNumber ) ) .createInformation() @@ -196,7 +196,7 @@ public abstract class AbstractCompositionDefinition extends AbstractNonIdentifie return ( (EntityDefinition) getSource() ).getEntityPersister(); } else { - return ( (AbstractCompositionDefinition) getSource() ).locateOwningPersister(); + return ( (AbstractCompositionAttribute) getSource() ).locateOwningPersister(); } } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/component/CompositeBasedAssociationAttribute.java b/hibernate-core/src/main/java/org/hibernate/tuple/component/CompositeBasedAssociationAttribute.java index 81c7f343f8..72eb5eac0b 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/component/CompositeBasedAssociationAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/component/CompositeBasedAssociationAttribute.java @@ -55,7 +55,7 @@ public class CompositeBasedAssociationAttribute private Joinable joinable; public CompositeBasedAssociationAttribute( - AbstractCompositionDefinition source, + AbstractCompositionAttribute source, SessionFactoryImplementor factory, int attributeNumber, String attributeName, diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/component/CompositionBasedCompositionAttribute.java b/hibernate-core/src/main/java/org/hibernate/tuple/component/CompositionBasedCompositionAttribute.java index 7beee25984..4a154f130d 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/component/CompositionBasedCompositionAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/component/CompositionBasedCompositionAttribute.java @@ -32,7 +32,7 @@ import org.hibernate.type.CompositeType; * @author Steve Ebersole */ public class CompositionBasedCompositionAttribute - extends AbstractCompositionDefinition + extends AbstractCompositionAttribute implements CompositionDefinition { public CompositionBasedCompositionAttribute( CompositionDefinition source, diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityBasedCompositionAttribute.java b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityBasedCompositionAttribute.java index e283cae94b..66a7242a5f 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityBasedCompositionAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityBasedCompositionAttribute.java @@ -25,7 +25,7 @@ package org.hibernate.tuple.entity; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.persister.entity.EntityPersister; -import org.hibernate.tuple.component.AbstractCompositionDefinition; +import org.hibernate.tuple.component.AbstractCompositionAttribute; import org.hibernate.persister.walking.spi.CompositionDefinition; import org.hibernate.tuple.BaselineAttributeInformation; import org.hibernate.type.CompositeType; @@ -34,7 +34,7 @@ import org.hibernate.type.CompositeType; * @author Steve Ebersole */ public class EntityBasedCompositionAttribute - extends AbstractCompositionDefinition + extends AbstractCompositionAttribute implements CompositionDefinition { public EntityBasedCompositionAttribute( diff --git a/hibernate-core/src/test/java/org/hibernate/loader/EncapsulatedCompositeAttributeResultSetProcessorTest.java b/hibernate-core/src/test/java/org/hibernate/loader/EncapsulatedCompositeAttributeResultSetProcessorTest.java index 3f76e0607b..ca0cd1aeab 100644 --- a/hibernate-core/src/test/java/org/hibernate/loader/EncapsulatedCompositeAttributeResultSetProcessorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/loader/EncapsulatedCompositeAttributeResultSetProcessorTest.java @@ -42,6 +42,7 @@ import javax.persistence.EnumType; import javax.persistence.Enumerated; import javax.persistence.FetchType; import javax.persistence.Id; +import javax.persistence.ManyToOne; import org.junit.Test; @@ -60,6 +61,7 @@ import org.hibernate.loader.spi.LoadQueryAliasResolutionContext; import org.hibernate.loader.spi.NamedParameterContext; import org.hibernate.loader.spi.NoOpLoadPlanAdvisor; import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.test.component.cascading.toone.PersonalInfo; import org.hibernate.testing.FailureExpected; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.testing.junit4.ExtraAssertions; @@ -128,12 +130,15 @@ public class EncapsulatedCompositeAttributeResultSetProcessorTest extends BaseCo session.close(); } - /* @Test public void testNestedCompositeElementCollectionProcessing() throws Exception { // create some test data Session session = openSession(); session.beginTransaction(); + Person person = new Person(); + person.id = 1; + person.name = "Joe Blow"; + session.save( person ); Customer customer = new Customer(); customer.id = 1L; Investment investment1 = new Investment(); @@ -142,6 +147,7 @@ public class EncapsulatedCompositeAttributeResultSetProcessorTest extends BaseCo investment1.monetaryAmount = new MonetaryAmount(); investment1.monetaryAmount.currency = MonetaryAmount.CurrencyCode.USD; investment1.monetaryAmount.amount = BigDecimal.valueOf( 1234, 2 ); + investment1.performedBy = person; Investment investment2 = new Investment(); investment2.description = "bond"; investment2.date = new Date(); @@ -173,11 +179,11 @@ public class EncapsulatedCompositeAttributeResultSetProcessorTest extends BaseCo // clean up test data session = openSession(); session.beginTransaction(); - session.createQuery( "delete Customer" ).executeUpdate(); + session.delete( customerWork.investments.get( 0 ).performedBy ); + session.delete( customerWork ); session.getTransaction().commit(); session.close(); } - */ private List getResults(EntityPersister entityPersister ) { final SingleRootReturnLoadPlanBuilderStrategy strategy = new SingleRootReturnLoadPlanBuilderStrategy( @@ -288,6 +294,7 @@ public class EncapsulatedCompositeAttributeResultSetProcessorTest extends BaseCo private MonetaryAmount monetaryAmount; private String description; private Date date; + private Person performedBy; @Embedded public MonetaryAmount getMonetaryAmount() { @@ -308,6 +315,13 @@ public class EncapsulatedCompositeAttributeResultSetProcessorTest extends BaseCo public void setDate(Date date) { this.date = date; } + @ManyToOne + public Person getPerformedBy() { + return performedBy; + } + public void setPerformedBy(Person performedBy) { + this.performedBy = performedBy; + } } @Embeddable diff --git a/hibernate-core/src/test/java/org/hibernate/persister/walking/BasicWalkingTest.java b/hibernate-core/src/test/java/org/hibernate/persister/walking/BasicWalkingTest.java index da8bc7f961..411a42f714 100644 --- a/hibernate-core/src/test/java/org/hibernate/persister/walking/BasicWalkingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/persister/walking/BasicWalkingTest.java @@ -38,6 +38,7 @@ 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.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; @@ -168,6 +169,28 @@ public class BasicWalkingTest extends BaseCoreFunctionalTestCase { ); } + @Override + public void startingCompositeElement(CompositionElementDefinition compositionElementDefinition) { + System.out.println( + String.format( + "%s Starting composite (%s)", + StringHelper.repeat( ">>", ++depth ), + compositionElementDefinition.toString() + ) + ); + } + + @Override + public void finishingCompositeElement(CompositionElementDefinition compositionElementDefinition) { + System.out.println( + String.format( + "%s Finishing composite (%s)", + StringHelper.repeat( ">>", depth-- ), + compositionElementDefinition.toString() + ) + ); + } + @Override public boolean startingAttribute(AttributeDefinition attributeDefinition) { System.out.println(