diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java index a5d70ad49e..67572aaaed 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java @@ -469,6 +469,10 @@ public final class SessionFactoryImpl ); // after *all* persisters and named queries are registered + for ( EntityPersister persister : entityPersisters.values() ) { + persister.generateEntityDefinition(); + } + for ( EntityPersister persister : entityPersisters.values() ) { persister.postInstantiate(); registerEntityNameResolvers( persister ); diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/AbstractCompositeEntityIdentifierDescription.java b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/AbstractCompositeEntityIdentifierDescription.java index dea24e7fca..abbec6b213 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/AbstractCompositeEntityIdentifierDescription.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/AbstractCompositeEntityIdentifierDescription.java @@ -23,16 +23,11 @@ */ package org.hibernate.loader.plan2.build.internal.returns; -import org.hibernate.engine.FetchStrategy; import org.hibernate.loader.PropertyPath; +import org.hibernate.loader.plan2.build.spi.ExpandingCompositeQuerySpace; import org.hibernate.loader.plan2.build.spi.ExpandingEntityIdentifierDescription; -import org.hibernate.loader.plan2.build.spi.LoadPlanBuildingContext; -import org.hibernate.loader.plan2.spi.CompositeQuerySpace; -import org.hibernate.loader.plan2.spi.EntityFetch; import org.hibernate.loader.plan2.spi.EntityReference; import org.hibernate.loader.plan2.spi.FetchSource; -import org.hibernate.loader.plan2.spi.Join; -import org.hibernate.persister.walking.spi.AssociationAttributeDefinition; import org.hibernate.type.CompositeType; /** @@ -47,7 +42,7 @@ public abstract class AbstractCompositeEntityIdentifierDescription protected AbstractCompositeEntityIdentifierDescription( EntityReference entityReference, - CompositeQuerySpace compositeQuerySpace, + ExpandingCompositeQuerySpace compositeQuerySpace, CompositeType identifierType, PropertyPath propertyPath) { super( identifierType, compositeQuerySpace, false, propertyPath ); @@ -59,6 +54,11 @@ public abstract class AbstractCompositeEntityIdentifierDescription return getFetches().length > 0; } + @Override + public boolean hasBidirectionalEntityReferences() { + return getBidirectionalEntityReferences().length > 0; + } + @Override public FetchSource getSource() { // the source for this (as a Fetch) is the entity reference diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/AbstractCompositeFetch.java b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/AbstractCompositeFetch.java index d12027706a..3266d6a4a9 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/AbstractCompositeFetch.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/AbstractCompositeFetch.java @@ -23,63 +23,40 @@ */ package org.hibernate.loader.plan2.build.internal.returns; -import java.util.ArrayList; -import java.util.List; - import org.hibernate.engine.FetchStrategy; import org.hibernate.engine.FetchStyle; import org.hibernate.engine.FetchTiming; import org.hibernate.loader.PropertyPath; -import org.hibernate.loader.plan2.build.spi.ExpandingFetchSource; -import org.hibernate.loader.plan2.build.spi.ExpandingQuerySpace; +import org.hibernate.loader.plan2.build.spi.ExpandingCompositeQuerySpace; import org.hibernate.loader.plan2.build.spi.LoadPlanBuildingContext; -import org.hibernate.loader.plan2.spi.BidirectionalEntityFetch; import org.hibernate.loader.plan2.spi.CollectionFetch; import org.hibernate.loader.plan2.spi.CompositeFetch; -import org.hibernate.loader.plan2.spi.CompositeQuerySpace; -import org.hibernate.loader.plan2.spi.EntityFetch; import org.hibernate.loader.plan2.spi.EntityReference; -import org.hibernate.loader.plan2.spi.Fetch; import org.hibernate.loader.plan2.spi.FetchSource; -import org.hibernate.loader.plan2.spi.Join; -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.AttributeDefinition; -import org.hibernate.persister.walking.spi.CompositionDefinition; import org.hibernate.persister.walking.spi.WalkingException; -import org.hibernate.type.CollectionType; import org.hibernate.type.CompositeType; -import org.hibernate.type.EntityType; import org.hibernate.type.Type; /** * @author Steve Ebersole * @author Gail Badner */ -public abstract class AbstractCompositeFetch implements CompositeFetch, ExpandingFetchSource { +public abstract class AbstractCompositeFetch extends AbstractExpandingFetchSource implements CompositeFetch { private static final FetchStrategy FETCH_STRATEGY = new FetchStrategy( FetchTiming.IMMEDIATE, FetchStyle.JOIN ); private final CompositeType compositeType; - private final CompositeQuerySpace compositeQuerySpace; - private final PropertyPath propertyPath; private final boolean allowCollectionFetches; - private List fetches; - protected AbstractCompositeFetch( CompositeType compositeType, - CompositeQuerySpace compositeQuerySpace, - boolean allowCollectionFetches, PropertyPath propertyPath) { + ExpandingCompositeQuerySpace compositeQuerySpace, + boolean allowCollectionFetches, + PropertyPath propertyPath) { + super( compositeQuerySpace, propertyPath ); this.compositeType = compositeType; - this.compositeQuerySpace = compositeQuerySpace; this.allowCollectionFetches = allowCollectionFetches; - this.propertyPath = propertyPath; - } - - @SuppressWarnings("UnusedParameters") - protected CompositeQuerySpace resolveCompositeQuerySpace(LoadPlanBuildingContext loadPlanBuildingContext) { - return compositeQuerySpace; } @Override @@ -106,101 +83,21 @@ public abstract class AbstractCompositeFetch implements CompositeFetch, Expandin ); } - @Override - public String getQuerySpaceUid() { - return compositeQuerySpace.getUid(); - } - @Override public void validateFetchPlan(FetchStrategy fetchStrategy, AttributeDefinition attributeDefinition) { // anything to do here? } - @Override - public EntityFetch buildEntityFetch( - AssociationAttributeDefinition attributeDefinition, - FetchStrategy fetchStrategy, - LoadPlanBuildingContext loadPlanBuildingContext) { - return buildEntityFetch( attributeDefinition, fetchStrategy, null, loadPlanBuildingContext ); - } - - @Override - public BidirectionalEntityFetch buildBidirectionalEntityFetch( - AssociationAttributeDefinition attributeDefinition, - FetchStrategy fetchStrategy, - EntityReference entityReference, - LoadPlanBuildingContext loadPlanBuildingContext) { - return (BidirectionalEntityFetch) buildEntityFetch( - attributeDefinition, fetchStrategy, entityReference, loadPlanBuildingContext - ); - } - - private EntityFetch buildEntityFetch( - AssociationAttributeDefinition attributeDefinition, - FetchStrategy fetchStrategy, - EntityReference targetEntityReference, - LoadPlanBuildingContext loadPlanBuildingContext) { - final EntityType fetchedType = (EntityType) attributeDefinition.getType(); - final EntityPersister fetchedPersister = loadPlanBuildingContext.getSessionFactory().getEntityPersister( - fetchedType.getAssociatedEntityName() - ); - - if ( fetchedPersister == null ) { - throw new WalkingException( - String.format( - "Unable to locate EntityPersister [%s] for fetch [%s]", - fetchedType.getAssociatedEntityName(), - attributeDefinition.getName() - ) - ); - } - - final ExpandingQuerySpace leftHandSide = (ExpandingQuerySpace) resolveCompositeQuerySpace( - loadPlanBuildingContext - ); - final EntityFetch fetch; - if ( targetEntityReference == null ) { - final Join join = leftHandSide.addEntityJoin( - attributeDefinition, - fetchedPersister, - loadPlanBuildingContext.getQuerySpaces().generateImplicitUid(), - attributeDefinition.isNullable() - ); - fetch = new EntityFetchImpl( this, attributeDefinition, fetchStrategy, join ); - } - else { - fetch = new BidirectionalEntityFetchImpl( this, attributeDefinition, fetchStrategy, targetEntityReference ); - } - addFetch( fetch ); - return fetch; - } - - private void addFetch(Fetch fetch) { - if ( fetches == null ) { - fetches = new ArrayList(); - } - fetches.add( fetch ); - } - - @Override - public CompositeFetch buildCompositeFetch( - CompositionDefinition attributeDefinition, - LoadPlanBuildingContext loadPlanBuildingContext) { - final ExpandingQuerySpace leftHandSide = (ExpandingQuerySpace) resolveCompositeQuerySpace( loadPlanBuildingContext ); - final Join join = leftHandSide.addCompositeJoin( - attributeDefinition, - loadPlanBuildingContext.getQuerySpaces().generateImplicitUid() - ); - - final NestedCompositeFetchImpl fetch = new NestedCompositeFetchImpl( + protected CompositeFetch createCompositeFetch( + CompositeType compositeType, + ExpandingCompositeQuerySpace compositeQuerySpace) { + return new NestedCompositeFetchImpl( this, - attributeDefinition.getType(), - (CompositeQuerySpace) join.getRightHandSide(), + compositeType, + compositeQuerySpace, allowCollectionFetches, getPropertyPath() ); - addFetch( fetch ); - return fetch; } @Override @@ -212,50 +109,11 @@ public abstract class AbstractCompositeFetch implements CompositeFetch, Expandin throw new WalkingException( String.format( "This composite path [%s] does not allow collection fetches (composite id or composite collection index/element", - propertyPath.getFullPath() + getPropertyPath().getFullPath() ) ); } - - // general question here wrt Joins and collection fetches... do we create multiple Joins for many-to-many, - // for example, or do we allow the Collection QuerySpace to handle that? - - final CollectionType fetchedType = (CollectionType) attributeDefinition.getType(); - final CollectionPersister fetchedPersister = loadPlanBuildingContext.getSessionFactory().getCollectionPersister( - fetchedType.getRole() - ); - - if ( fetchedPersister == null ) { - throw new WalkingException( - String.format( - "Unable to locate CollectionPersister [%s] for fetch [%s]", - fetchedType.getRole(), - attributeDefinition.getName() - ) - ); - } - final ExpandingQuerySpace leftHandSide = (ExpandingQuerySpace) loadPlanBuildingContext.getQuerySpaces().getQuerySpaceByUid( - getQuerySpaceUid() - ); - final Join join = leftHandSide.addCollectionJoin( - attributeDefinition, - fetchedPersister, - loadPlanBuildingContext.getQuerySpaces().generateImplicitUid() - ); - final CollectionFetch fetch = new CollectionFetchImpl( - this, - attributeDefinition, - fetchStrategy, - join, - loadPlanBuildingContext - ); - addFetch( fetch ); - return fetch; - } - - @Override - public PropertyPath getPropertyPath() { - return propertyPath; + return super.buildCollectionFetch( attributeDefinition, fetchStrategy, loadPlanBuildingContext ); } @Override @@ -278,12 +136,6 @@ public abstract class AbstractCompositeFetch implements CompositeFetch, Expandin return null; } - @Override - public Fetch[] getFetches() { - return (fetches == null) ? NO_FETCHES : fetches.toArray( new Fetch[fetches.size()] ); - } - - // this is being removed to be more ogm/search friendly @Override public String[] toSqlSelectFragments(String alias) { diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/AbstractEntityReference.java b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/AbstractEntityReference.java index 6eabe81bd5..a2a9cb06b6 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/AbstractEntityReference.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/AbstractEntityReference.java @@ -23,56 +23,36 @@ */ package org.hibernate.loader.plan2.build.internal.returns; -import java.util.ArrayList; -import java.util.List; - -import org.hibernate.engine.FetchStrategy; import org.hibernate.loader.PropertyPath; +import org.hibernate.loader.plan2.build.spi.ExpandingCompositeQuerySpace; import org.hibernate.loader.plan2.build.spi.ExpandingEntityQuerySpace; -import org.hibernate.loader.plan2.build.spi.ExpandingFetchSource; -import org.hibernate.loader.plan2.build.spi.ExpandingQuerySpace; -import org.hibernate.loader.plan2.build.spi.LoadPlanBuildingContext; -import org.hibernate.loader.plan2.spi.BidirectionalEntityFetch; -import org.hibernate.loader.plan2.spi.CollectionFetch; import org.hibernate.loader.plan2.spi.CompositeFetch; -import org.hibernate.loader.plan2.spi.CompositeQuerySpace; -import org.hibernate.loader.plan2.spi.EntityFetch; import org.hibernate.loader.plan2.spi.EntityIdentifierDescription; -import org.hibernate.loader.plan2.spi.EntityQuerySpace; import org.hibernate.loader.plan2.spi.EntityReference; -import org.hibernate.loader.plan2.spi.Fetch; import org.hibernate.loader.plan2.spi.Join; -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.persister.walking.spi.EncapsulatedEntityIdentifierDefinition; import org.hibernate.persister.walking.spi.EntityIdentifierDefinition; -import org.hibernate.persister.walking.spi.WalkingException; -import org.hibernate.type.CollectionType; import org.hibernate.type.CompositeType; -import org.hibernate.type.EntityType; import org.hibernate.type.Type; /** * @author Steve Ebersole */ -public abstract class AbstractEntityReference implements EntityReference, ExpandingFetchSource { - private final EntityQuerySpace entityQuerySpace; - private final PropertyPath propertyPath; +public abstract class AbstractEntityReference extends AbstractExpandingFetchSource implements EntityReference { private final EntityIdentifierDescription identifierDescription; - private List fetches; - public AbstractEntityReference( - EntityQuerySpace entityQuerySpace, + ExpandingEntityQuerySpace entityQuerySpace, PropertyPath propertyPath) { - this.entityQuerySpace = entityQuerySpace; - this.propertyPath = propertyPath; + super( entityQuerySpace, propertyPath ); this.identifierDescription = buildIdentifierDescription(); } + private ExpandingEntityQuerySpace expandingEntityQuerySpace() { + return (ExpandingEntityQuerySpace) expandingQuerySpace(); + } /** * Builds just the first level of identifier description. This will be either a simple id descriptor (String, @@ -81,8 +61,7 @@ public abstract class AbstractEntityReference implements EntityReference, Expand * @return the descriptor for the identifier */ private EntityIdentifierDescription buildIdentifierDescription() { - final EntityPersister persister = entityQuerySpace.getEntityPersister(); - final EntityIdentifierDefinition identifierDefinition = persister.getEntityKeyDefinition(); + final EntityIdentifierDefinition identifierDefinition = getEntityPersister().getEntityKeyDefinition(); if ( identifierDefinition.isEncapsulated() ) { final EncapsulatedEntityIdentifierDefinition encapsulatedIdentifierDefinition = (EncapsulatedEntityIdentifierDefinition) identifierDefinition; @@ -93,7 +72,7 @@ public abstract class AbstractEntityReference implements EntityReference, Expand } // if we get here, we know we have a composite identifier... - final Join join = ( (ExpandingEntityQuerySpace) entityQuerySpace ).makeCompositeIdentifierJoin(); + final Join join = expandingEntityQuerySpace().makeCompositeIdentifierJoin(); return identifierDefinition.isEncapsulated() ? buildEncapsulatedCompositeIdentifierDescription( join ) : buildNonEncapsulatedCompositeIdentifierDescription( join ); @@ -102,18 +81,18 @@ public abstract class AbstractEntityReference implements EntityReference, Expand private NonEncapsulatedEntityIdentifierDescription buildNonEncapsulatedCompositeIdentifierDescription(Join compositeJoin) { return new NonEncapsulatedEntityIdentifierDescription( this, - (CompositeQuerySpace) compositeJoin.getRightHandSide(), - (CompositeType) entityQuerySpace.getEntityPersister().getIdentifierType(), - propertyPath.append( "id" ) + (ExpandingCompositeQuerySpace) compositeJoin.getRightHandSide(), + (CompositeType) getEntityPersister().getIdentifierType(), + getPropertyPath().append( "id" ) ); } private EncapsulatedEntityIdentifierDescription buildEncapsulatedCompositeIdentifierDescription(Join compositeJoin) { return new EncapsulatedEntityIdentifierDescription( this, - (CompositeQuerySpace) compositeJoin.getRightHandSide(), - (CompositeType) entityQuerySpace.getEntityPersister().getIdentifierType(), - propertyPath.append( "id" ) + (ExpandingCompositeQuerySpace) compositeJoin.getRightHandSide(), + (CompositeType) getEntityPersister().getIdentifierType(), + getPropertyPath().append( "id" ) ); } @@ -122,18 +101,9 @@ public abstract class AbstractEntityReference implements EntityReference, Expand return this; } - protected EntityQuerySpace getEntityQuerySpace() { - return entityQuerySpace; - } - - @Override - public String getQuerySpaceUid() { - return getEntityQuerySpace().getUid(); - } - @Override public EntityPersister getEntityPersister() { - return entityQuerySpace.getEntityPersister(); + return expandingEntityQuerySpace().getEntityPersister(); } @Override @@ -141,141 +111,15 @@ public abstract class AbstractEntityReference implements EntityReference, Expand return identifierDescription; } - @Override - public PropertyPath getPropertyPath() { - return propertyPath; - } - - @Override - public Fetch[] getFetches() { - return fetches == null ? NO_FETCHES : fetches.toArray( new Fetch[ fetches.size() ] ); - } - - @Override - public EntityFetch buildEntityFetch( - AssociationAttributeDefinition attributeDefinition, - FetchStrategy fetchStrategy, - LoadPlanBuildingContext loadPlanBuildingContext) { - return buildEntityFetch( attributeDefinition, fetchStrategy, null, loadPlanBuildingContext ); - } - - @Override - public BidirectionalEntityFetch buildBidirectionalEntityFetch( - AssociationAttributeDefinition attributeDefinition, - FetchStrategy fetchStrategy, - EntityReference targetEntityReference, - LoadPlanBuildingContext loadPlanBuildingContext) { - return (BidirectionalEntityFetch) buildEntityFetch( - attributeDefinition, fetchStrategy, targetEntityReference, loadPlanBuildingContext - ); - } - - - private EntityFetch buildEntityFetch( - AssociationAttributeDefinition attributeDefinition, - FetchStrategy fetchStrategy, - EntityReference targetEntityReference, - LoadPlanBuildingContext loadPlanBuildingContext) { - final EntityType fetchedType = (EntityType) attributeDefinition.getType(); - final EntityPersister fetchedPersister = loadPlanBuildingContext.getSessionFactory().getEntityPersister( - fetchedType.getAssociatedEntityName() - ); - - if ( fetchedPersister == null ) { - throw new WalkingException( - String.format( - "Unable to locate EntityPersister [%s] for fetch [%s]", - fetchedType.getAssociatedEntityName(), - attributeDefinition.getName() - ) - ); - } - - final ExpandingQuerySpace leftHandSide = (ExpandingQuerySpace) entityQuerySpace; - final EntityFetch fetch; - if ( targetEntityReference == null ) { - final Join join = leftHandSide.addEntityJoin( - attributeDefinition, - fetchedPersister, - loadPlanBuildingContext.getQuerySpaces().generateImplicitUid(), - attributeDefinition.isNullable() - ); - fetch = new EntityFetchImpl( this, attributeDefinition, fetchStrategy, join ); - } - else { - fetch = new BidirectionalEntityFetchImpl( this, attributeDefinition, fetchStrategy, targetEntityReference ); - } - addFetch( fetch ); - return fetch; - } - - private void addFetch(Fetch fetch) { - if ( fetches == null ) { - fetches = new ArrayList(); - } - fetches.add( fetch ); - } - - @Override - public CompositeFetch buildCompositeFetch( - CompositionDefinition attributeDefinition, - LoadPlanBuildingContext loadPlanBuildingContext) { - final ExpandingQuerySpace leftHandSide = (ExpandingQuerySpace) entityQuerySpace; - final Join join = leftHandSide.addCompositeJoin( - attributeDefinition, - loadPlanBuildingContext.getQuerySpaces().generateImplicitUid() - ); - - final CompositeFetchImpl fetch = new CompositeFetchImpl( + protected CompositeFetch createCompositeFetch( + CompositeType compositeType, + ExpandingCompositeQuerySpace compositeQuerySpace) { + return new CompositeFetchImpl( this, - attributeDefinition.getType(), - (CompositeQuerySpace) join.getRightHandSide(), + compositeType, + compositeQuerySpace, true, getPropertyPath() ); - addFetch( fetch ); - return fetch; - } - - @Override - public CollectionFetch buildCollectionFetch( - AssociationAttributeDefinition attributeDefinition, - FetchStrategy fetchStrategy, - LoadPlanBuildingContext loadPlanBuildingContext) { - - // general question here wrt Joins and collection fetches... do we create multiple Joins for many-to-many, - // for example, or do we allow the Collection QuerySpace to handle that? - - final CollectionType fetchedType = (CollectionType) attributeDefinition.getType(); - final CollectionPersister fetchedPersister = loadPlanBuildingContext.getSessionFactory().getCollectionPersister( - fetchedType.getRole() - ); - - if ( fetchedPersister == null ) { - throw new WalkingException( - String.format( - "Unable to locate CollectionPersister [%s] for fetch [%s]", - fetchedType.getRole(), - attributeDefinition.getName() - ) - ); - } - final ExpandingQuerySpace leftHandSide = (ExpandingQuerySpace) loadPlanBuildingContext.getQuerySpaces().getQuerySpaceByUid( - getQuerySpaceUid() - ); - final Join join = leftHandSide.addCollectionJoin( - attributeDefinition, - fetchedPersister, - loadPlanBuildingContext.getQuerySpaces().generateImplicitUid() - ); - final CollectionFetch fetch = new CollectionFetchImpl( - this, - attributeDefinition, - fetchStrategy, - join, - loadPlanBuildingContext - ); - addFetch( fetch ); - return fetch; } } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/AbstractExpandingFetchSource.java b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/AbstractExpandingFetchSource.java new file mode 100644 index 0000000000..2e4509680c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/AbstractExpandingFetchSource.java @@ -0,0 +1,236 @@ +/* + * 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.plan2.build.internal.returns; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.engine.FetchStrategy; +import org.hibernate.loader.PropertyPath; +import org.hibernate.loader.plan2.build.spi.ExpandingCompositeQuerySpace; +import org.hibernate.loader.plan2.build.spi.ExpandingFetchSource; +import org.hibernate.loader.plan2.build.spi.ExpandingQuerySpace; +import org.hibernate.loader.plan2.build.spi.LoadPlanBuildingContext; +import org.hibernate.loader.plan2.spi.BidirectionalEntityReference; +import org.hibernate.loader.plan2.spi.CollectionFetch; +import org.hibernate.loader.plan2.spi.CompositeFetch; +import org.hibernate.loader.plan2.spi.EntityFetch; +import org.hibernate.loader.plan2.spi.EntityReference; +import org.hibernate.loader.plan2.spi.Fetch; +import org.hibernate.loader.plan2.spi.Join; +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.persister.walking.spi.WalkingException; +import org.hibernate.type.CollectionType; +import org.hibernate.type.CompositeType; +import org.hibernate.type.EntityType; + +/** + * @author Gail Badner + */ +public abstract class AbstractExpandingFetchSource implements ExpandingFetchSource { + /** + * Convenient constant for returning no fetches from {@link #getFetches()} + */ + private static final Fetch[] NO_FETCHES = new Fetch[0]; + + /** + * Convenient constant for returning no fetches from {@link #getFetches()} + */ + private static final BidirectionalEntityReference[] NO_BIDIRECTIONAL_ENTITY_REFERENCES = + new BidirectionalEntityReference[0]; + + private final ExpandingQuerySpace querySpace; + private final PropertyPath propertyPath; + private List fetches; + private List bidirectionalEntityReferences; + + public AbstractExpandingFetchSource(ExpandingQuerySpace querySpace, PropertyPath propertyPath) { + this.querySpace = querySpace; + this.propertyPath = propertyPath; + } + + @Override + public final String getQuerySpaceUid() { + return querySpace.getUid(); + } + + protected final ExpandingQuerySpace expandingQuerySpace() { + return querySpace; + } + + @Override + public final PropertyPath getPropertyPath() { + return propertyPath; + } + + @Override + public Fetch[] getFetches() { + return fetches == null ? NO_FETCHES : fetches.toArray( new Fetch[ fetches.size() ] ); + } + + private void addFetch(Fetch fetch) { + if ( fetches == null ) { + fetches = new ArrayList(); + } + fetches.add( fetch ); + } + + @Override + public BidirectionalEntityReference[] getBidirectionalEntityReferences() { + return bidirectionalEntityReferences == null ? + NO_BIDIRECTIONAL_ENTITY_REFERENCES : + bidirectionalEntityReferences.toArray( + new BidirectionalEntityReference[ bidirectionalEntityReferences.size() ] + ); + } + + private void addBidirectionalEntityReference(BidirectionalEntityReference bidirectionalEntityReference) { + if ( bidirectionalEntityReferences == null ) { + bidirectionalEntityReferences = new ArrayList(); + } + bidirectionalEntityReferences.add( bidirectionalEntityReference ); + } + + @Override + public EntityFetch buildEntityFetch( + AssociationAttributeDefinition attributeDefinition, + FetchStrategy fetchStrategy, + LoadPlanBuildingContext loadPlanBuildingContext) { + final EntityType fetchedType = (EntityType) attributeDefinition.getType(); + final EntityPersister fetchedPersister = loadPlanBuildingContext.getSessionFactory().getEntityPersister( + fetchedType.getAssociatedEntityName() + ); + + if ( fetchedPersister == null ) { + throw new WalkingException( + String.format( + "Unable to locate EntityPersister [%s] for fetch [%s]", + fetchedType.getAssociatedEntityName(), + attributeDefinition.getName() + ) + ); + } + + final Join join = querySpace.addEntityJoin( + attributeDefinition, + fetchedPersister, + loadPlanBuildingContext.getQuerySpaces().generateImplicitUid(), + attributeDefinition.isNullable() + ); + final EntityFetch fetch = new EntityFetchImpl( this, attributeDefinition, fetchStrategy, join ); + addFetch( fetch ); + return fetch; + } + + @Override + public BidirectionalEntityReference buildBidirectionalEntityReference( + AssociationAttributeDefinition attributeDefinition, + FetchStrategy fetchStrategy, + EntityReference targetEntityReference, + LoadPlanBuildingContext loadPlanBuildingContext) { + final EntityType fetchedType = (EntityType) attributeDefinition.getType(); + final EntityPersister fetchedPersister = loadPlanBuildingContext.getSessionFactory().getEntityPersister( + fetchedType.getAssociatedEntityName() + ); + + if ( fetchedPersister == null ) { + throw new WalkingException( + String.format( + "Unable to locate EntityPersister [%s] for bidirectional entity reference [%s]", + fetchedType.getAssociatedEntityName(), + attributeDefinition.getName() + ) + ); + } + + final BidirectionalEntityReference bidirectionalEntityReference = + new BidirectionalEntityReferenceImpl( this, attributeDefinition, targetEntityReference ); + addBidirectionalEntityReference( bidirectionalEntityReference ); + return bidirectionalEntityReference; + } + + protected abstract CompositeFetch createCompositeFetch( + CompositeType compositeType, + ExpandingCompositeQuerySpace compositeQuerySpace); + + @Override + public CompositeFetch buildCompositeFetch( + CompositionDefinition attributeDefinition, + LoadPlanBuildingContext loadPlanBuildingContext) { + final ExpandingQuerySpace leftHandSide = expandingQuerySpace(); + final Join join = leftHandSide.addCompositeJoin( + attributeDefinition, + loadPlanBuildingContext.getQuerySpaces().generateImplicitUid() + ); + final CompositeFetch fetch = createCompositeFetch( + attributeDefinition.getType(), + (ExpandingCompositeQuerySpace) join.getRightHandSide() + ); + addFetch( fetch ); + return fetch; + } + + @Override + public CollectionFetch buildCollectionFetch( + AssociationAttributeDefinition attributeDefinition, + FetchStrategy fetchStrategy, + LoadPlanBuildingContext loadPlanBuildingContext) { + + // general question here wrt Joins and collection fetches... do we create multiple Joins for many-to-many, + // for example, or do we allow the Collection QuerySpace to handle that? + + final CollectionType fetchedType = (CollectionType) attributeDefinition.getType(); + final CollectionPersister fetchedPersister = loadPlanBuildingContext.getSessionFactory().getCollectionPersister( + fetchedType.getRole() + ); + + if ( fetchedPersister == null ) { + throw new WalkingException( + String.format( + "Unable to locate CollectionPersister [%s] for fetch [%s]", + fetchedType.getRole(), + attributeDefinition.getName() + ) + ); + } + final Join join = querySpace.addCollectionJoin( + attributeDefinition, + fetchedPersister, + loadPlanBuildingContext.getQuerySpaces().generateImplicitUid() + ); + final CollectionFetch fetch = new CollectionFetchImpl( + this, + attributeDefinition, + fetchStrategy, + join, + loadPlanBuildingContext + ); + addFetch( fetch ); + return fetch; + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/BidirectionalEntityFetchImpl.java b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/BidirectionalEntityReferenceImpl.java similarity index 69% rename from hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/BidirectionalEntityFetchImpl.java rename to hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/BidirectionalEntityReferenceImpl.java index 8f4822bf91..7f99cccf57 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/BidirectionalEntityFetchImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/BidirectionalEntityReferenceImpl.java @@ -23,18 +23,15 @@ */ package org.hibernate.loader.plan2.build.internal.returns; -import org.hibernate.engine.FetchStrategy; import org.hibernate.loader.PropertyPath; import org.hibernate.loader.plan2.build.spi.ExpandingFetchSource; -import org.hibernate.loader.plan2.spi.BidirectionalEntityFetch; -import org.hibernate.loader.plan2.spi.EntityFetch; +import org.hibernate.loader.plan2.spi.BidirectionalEntityReference; import org.hibernate.loader.plan2.spi.EntityIdentifierDescription; import org.hibernate.loader.plan2.spi.EntityReference; import org.hibernate.loader.plan2.spi.Fetch; import org.hibernate.loader.plan2.spi.FetchSource; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.walking.spi.AssociationAttributeDefinition; -import org.hibernate.type.EntityType; /** * Represents an entity fetch that is bi-directionally join fetched. @@ -45,21 +42,14 @@ import org.hibernate.type.EntityType; * * @author Steve Ebersole */ -public class BidirectionalEntityFetchImpl implements BidirectionalEntityFetch, EntityFetch { - private final ExpandingFetchSource fetchSource; - private final AssociationAttributeDefinition fetchedAttribute; - private final FetchStrategy fetchStrategy; +public class BidirectionalEntityReferenceImpl implements BidirectionalEntityReference { private final EntityReference targetEntityReference; private final PropertyPath propertyPath; - public BidirectionalEntityFetchImpl( + public BidirectionalEntityReferenceImpl( ExpandingFetchSource fetchSource, AssociationAttributeDefinition fetchedAttribute, - FetchStrategy fetchStrategy, EntityReference targetEntityReference) { - this.fetchSource = fetchSource; - this.fetchedAttribute = fetchedAttribute; - this.fetchStrategy = fetchStrategy; this.targetEntityReference = targetEntityReference; this.propertyPath = fetchSource.getPropertyPath().append( fetchedAttribute.getName() ); } @@ -68,41 +58,11 @@ public class BidirectionalEntityFetchImpl implements BidirectionalEntityFetch, E return targetEntityReference; } - @Override - public FetchSource getSource() { - return fetchSource; - } - @Override public PropertyPath getPropertyPath() { return propertyPath; } - @Override - public FetchStrategy getFetchStrategy() { - return fetchStrategy; - } - - @Override - public EntityType getFetchedType() { - return (EntityType) fetchedAttribute.getType(); - } - - @Override - public boolean isNullable() { - return fetchedAttribute.isNullable(); - } - - @Override - public String getAdditionalJoinConditions() { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - @Override - public String[] toSqlSelectFragments(String alias) { - return new String[0]; //To change body of implemented methods use File | Settings | File Templates. - } - @Override public String getQuerySpaceUid() { return targetEntityReference.getQuerySpaceUid(); @@ -110,7 +70,12 @@ public class BidirectionalEntityFetchImpl implements BidirectionalEntityFetch, E @Override public Fetch[] getFetches() { - return FetchSource.NO_FETCHES; + return targetEntityReference.getFetches(); + } + + @Override + public BidirectionalEntityReference[] getBidirectionalEntityReferences() { + return targetEntityReference.getBidirectionalEntityReferences(); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/CollectionFetchableElementCompositeGraph.java b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/CollectionFetchableElementCompositeGraph.java index 6f9e9f2344..fec985b1b9 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/CollectionFetchableElementCompositeGraph.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/CollectionFetchableElementCompositeGraph.java @@ -23,10 +23,10 @@ */ package org.hibernate.loader.plan2.build.internal.returns; +import org.hibernate.loader.plan2.build.spi.ExpandingCompositeQuerySpace; import org.hibernate.loader.plan2.spi.CollectionFetchableElement; import org.hibernate.loader.plan2.spi.CollectionReference; import org.hibernate.loader.plan2.spi.CompositeFetch; -import org.hibernate.loader.plan2.spi.CompositeQuerySpace; import org.hibernate.loader.plan2.spi.FetchSource; import org.hibernate.loader.plan2.spi.Join; import org.hibernate.type.CompositeType; @@ -45,7 +45,7 @@ public class CollectionFetchableElementCompositeGraph public CollectionFetchableElementCompositeGraph(CollectionReference collectionReference, Join compositeJoin) { super( (CompositeType) compositeJoin.getRightHandSide().getPropertyMapping().getType(), - (CompositeQuerySpace) compositeJoin.getRightHandSide(), + (ExpandingCompositeQuerySpace) compositeJoin.getRightHandSide(), false, // these property paths are just informational... collectionReference.getPropertyPath().append( "" ) diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/CollectionFetchableElementEntityGraph.java b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/CollectionFetchableElementEntityGraph.java index 820f873187..fb582d26be 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/CollectionFetchableElementEntityGraph.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/CollectionFetchableElementEntityGraph.java @@ -24,6 +24,7 @@ package org.hibernate.loader.plan2.build.internal.returns; import org.hibernate.engine.FetchStrategy; +import org.hibernate.loader.plan2.build.spi.ExpandingEntityQuerySpace; import org.hibernate.loader.plan2.spi.CollectionFetchableElement; import org.hibernate.loader.plan2.spi.CollectionReference; import org.hibernate.loader.plan2.spi.EntityQuerySpace; @@ -41,7 +42,7 @@ public class CollectionFetchableElementEntityGraph extends AbstractEntityReferen CollectionReference collectionReference, Join entityJoin) { super( - (EntityQuerySpace) entityJoin.getRightHandSide(), + (ExpandingEntityQuerySpace) entityJoin.getRightHandSide(), collectionReference.getPropertyPath().append( "" ) ); @@ -49,11 +50,6 @@ public class CollectionFetchableElementEntityGraph extends AbstractEntityReferen this.entityQuerySpace = (EntityQuerySpace) entityJoin.getRightHandSide(); } - @Override - protected EntityQuerySpace getEntityQuerySpace() { - return entityQuerySpace; - } - @Override public CollectionReference getCollectionReference() { return collectionReference; diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/CollectionFetchableIndexCompositeGraph.java b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/CollectionFetchableIndexCompositeGraph.java index 0adbcfb348..a0946929ee 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/CollectionFetchableIndexCompositeGraph.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/CollectionFetchableIndexCompositeGraph.java @@ -23,10 +23,10 @@ */ package org.hibernate.loader.plan2.build.internal.returns; +import org.hibernate.loader.plan2.build.spi.ExpandingCompositeQuerySpace; import org.hibernate.loader.plan2.spi.CollectionFetchableIndex; import org.hibernate.loader.plan2.spi.CollectionReference; import org.hibernate.loader.plan2.spi.CompositeFetch; -import org.hibernate.loader.plan2.spi.CompositeQuerySpace; import org.hibernate.loader.plan2.spi.FetchSource; import org.hibernate.loader.plan2.spi.Join; import org.hibernate.type.CompositeType; @@ -49,7 +49,7 @@ public class CollectionFetchableIndexCompositeGraph Join compositeJoin) { super( extractIndexType( compositeJoin ), - (CompositeQuerySpace) compositeJoin.getRightHandSide(), + (ExpandingCompositeQuerySpace) compositeJoin.getRightHandSide(), false, collectionReference.getPropertyPath().append( "" ) ); diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/CollectionFetchableIndexEntityGraph.java b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/CollectionFetchableIndexEntityGraph.java index 4184d80361..a92ff7c167 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/CollectionFetchableIndexEntityGraph.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/CollectionFetchableIndexEntityGraph.java @@ -24,6 +24,7 @@ package org.hibernate.loader.plan2.build.internal.returns; import org.hibernate.engine.FetchStrategy; +import org.hibernate.loader.plan2.build.spi.ExpandingEntityQuerySpace; import org.hibernate.loader.plan2.spi.CollectionFetchableIndex; import org.hibernate.loader.plan2.spi.CollectionReference; import org.hibernate.loader.plan2.spi.EntityQuerySpace; @@ -41,7 +42,7 @@ public class CollectionFetchableIndexEntityGraph extends AbstractEntityReference CollectionReference collectionReference, Join entityJoin) { super( - (EntityQuerySpace) entityJoin.getRightHandSide(), + (ExpandingEntityQuerySpace) entityJoin.getRightHandSide(), collectionReference.getPropertyPath().append( "" ) ); @@ -54,11 +55,6 @@ public class CollectionFetchableIndexEntityGraph extends AbstractEntityReference return collectionReference; } - @Override - protected EntityQuerySpace getEntityQuerySpace() { - return entityQuerySpace; - } - @Override public void validateFetchPlan(FetchStrategy fetchStrategy, AttributeDefinition attributeDefinition) { } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/CompositeFetchImpl.java b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/CompositeFetchImpl.java index 79b806ce2f..1e0efba032 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/CompositeFetchImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/CompositeFetchImpl.java @@ -24,8 +24,8 @@ package org.hibernate.loader.plan2.build.internal.returns; import org.hibernate.loader.PropertyPath; +import org.hibernate.loader.plan2.build.spi.ExpandingCompositeQuerySpace; import org.hibernate.loader.plan2.spi.CompositeFetch; -import org.hibernate.loader.plan2.spi.CompositeQuerySpace; import org.hibernate.loader.plan2.spi.FetchSource; import org.hibernate.type.CompositeType; @@ -38,7 +38,7 @@ public class CompositeFetchImpl extends AbstractCompositeFetch implements Compos protected CompositeFetchImpl( FetchSource source, CompositeType compositeType, - CompositeQuerySpace compositeQuerySpace, + ExpandingCompositeQuerySpace compositeQuerySpace, boolean allowCollectionFetches, PropertyPath propertyPath) { super( compositeType, compositeQuerySpace, allowCollectionFetches, propertyPath ); diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/EncapsulatedEntityIdentifierDescription.java b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/EncapsulatedEntityIdentifierDescription.java index 916e960b40..6324bf7bea 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/EncapsulatedEntityIdentifierDescription.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/EncapsulatedEntityIdentifierDescription.java @@ -24,6 +24,7 @@ package org.hibernate.loader.plan2.build.internal.returns; import org.hibernate.loader.PropertyPath; +import org.hibernate.loader.plan2.build.spi.ExpandingCompositeQuerySpace; import org.hibernate.loader.plan2.build.spi.ExpandingEntityIdentifierDescription; import org.hibernate.loader.plan2.spi.CompositeQuerySpace; import org.hibernate.loader.plan2.spi.EntityReference; @@ -49,7 +50,7 @@ public class EncapsulatedEntityIdentifierDescription */ protected EncapsulatedEntityIdentifierDescription( EntityReference entityReference, - CompositeQuerySpace compositeQuerySpace, + ExpandingCompositeQuerySpace compositeQuerySpace, CompositeType compositeType, PropertyPath propertyPath) { super( entityReference, compositeQuerySpace, compositeType, propertyPath ); diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/EntityFetchImpl.java b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/EntityFetchImpl.java index 6053fc1276..883ec88044 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/EntityFetchImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/EntityFetchImpl.java @@ -24,14 +24,13 @@ package org.hibernate.loader.plan2.build.internal.returns; import org.hibernate.engine.FetchStrategy; +import org.hibernate.loader.plan2.build.spi.ExpandingEntityQuerySpace; import org.hibernate.loader.plan2.build.spi.ExpandingFetchSource; import org.hibernate.loader.plan2.spi.EntityFetch; -import org.hibernate.loader.plan2.spi.EntityQuerySpace; import org.hibernate.loader.plan2.spi.FetchSource; import org.hibernate.loader.plan2.spi.Join; import org.hibernate.persister.walking.spi.AssociationAttributeDefinition; import org.hibernate.persister.walking.spi.AttributeDefinition; -import org.hibernate.persister.walking.spi.WalkingException; import org.hibernate.type.EntityType; /** @@ -48,7 +47,7 @@ public class EntityFetchImpl extends AbstractEntityReference implements EntityFe FetchStrategy fetchStrategy, Join fetchedJoin) { super( - (EntityQuerySpace) fetchedJoin.getRightHandSide(), + (ExpandingEntityQuerySpace) fetchedJoin.getRightHandSide(), fetchSource.getPropertyPath().append( fetchedAttribute.getName() ) ); diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/NestedCompositeFetchImpl.java b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/NestedCompositeFetchImpl.java index acfb2d58e0..7701702d63 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/NestedCompositeFetchImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/NestedCompositeFetchImpl.java @@ -24,8 +24,8 @@ package org.hibernate.loader.plan2.build.internal.returns; import org.hibernate.loader.PropertyPath; +import org.hibernate.loader.plan2.build.spi.ExpandingCompositeQuerySpace; import org.hibernate.loader.plan2.spi.CompositeFetch; -import org.hibernate.loader.plan2.spi.CompositeQuerySpace; import org.hibernate.loader.plan2.spi.FetchSource; import org.hibernate.type.CompositeType; @@ -38,7 +38,7 @@ public class NestedCompositeFetchImpl extends AbstractCompositeFetch { public NestedCompositeFetchImpl( CompositeFetch source, CompositeType type, - CompositeQuerySpace compositeQuerySpace, + ExpandingCompositeQuerySpace compositeQuerySpace, boolean allowCollectionFetches, PropertyPath propertyPath) { super( type, compositeQuerySpace, allowCollectionFetches, propertyPath ); this.source = source; diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/NonEncapsulatedEntityIdentifierDescription.java b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/NonEncapsulatedEntityIdentifierDescription.java index b8f3304056..4747d50d53 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/NonEncapsulatedEntityIdentifierDescription.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/NonEncapsulatedEntityIdentifierDescription.java @@ -24,7 +24,7 @@ package org.hibernate.loader.plan2.build.internal.returns; import org.hibernate.loader.PropertyPath; -import org.hibernate.loader.plan2.spi.CompositeQuerySpace; +import org.hibernate.loader.plan2.build.spi.ExpandingCompositeQuerySpace; import org.hibernate.loader.plan2.spi.EntityReference; import org.hibernate.type.CompositeType; @@ -45,7 +45,7 @@ public class NonEncapsulatedEntityIdentifierDescription extends AbstractComposit */ public NonEncapsulatedEntityIdentifierDescription( EntityReference entityReference, - CompositeQuerySpace compositeQuerySpace, + ExpandingCompositeQuerySpace compositeQuerySpace, CompositeType compositeType, PropertyPath propertyPath) { super( diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/SimpleEntityIdentifierDescriptionImpl.java b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/SimpleEntityIdentifierDescriptionImpl.java index de601a8d53..05a81b5903 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/SimpleEntityIdentifierDescriptionImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/returns/SimpleEntityIdentifierDescriptionImpl.java @@ -33,4 +33,9 @@ public class SimpleEntityIdentifierDescriptionImpl implements EntityIdentifierDe public boolean hasFetches() { return false; } + + @Override + public boolean hasBidirectionalEntityReferences() { + return false; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/spaces/CompositeQuerySpaceImpl.java b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/spaces/CompositeQuerySpaceImpl.java index d1d1e39781..ef8ebbc1cb 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/spaces/CompositeQuerySpaceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/spaces/CompositeQuerySpaceImpl.java @@ -25,8 +25,7 @@ package org.hibernate.loader.plan2.build.internal.spaces; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.loader.plan2.build.spi.AbstractQuerySpace; -import org.hibernate.loader.plan2.build.spi.ExpandingQuerySpace; -import org.hibernate.loader.plan2.spi.CompositeQuerySpace; +import org.hibernate.loader.plan2.build.spi.ExpandingCompositeQuerySpace; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.PropertyMapping; @@ -40,7 +39,7 @@ import org.hibernate.type.EntityType; /** * @author Steve Ebersole */ -public class CompositeQuerySpaceImpl extends AbstractQuerySpace implements CompositeQuerySpace, ExpandingQuerySpace { +public class CompositeQuerySpaceImpl extends AbstractQuerySpace implements ExpandingCompositeQuerySpace { private final CompositePropertyMapping compositeSubPropertyMapping; public CompositeQuerySpaceImpl( diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/spaces/EntityQuerySpaceImpl.java b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/spaces/EntityQuerySpaceImpl.java index 966db5efb2..1a96ca21b8 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/spaces/EntityQuerySpaceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/spaces/EntityQuerySpaceImpl.java @@ -26,13 +26,11 @@ package org.hibernate.loader.plan2.build.internal.spaces; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.loader.plan2.build.spi.AbstractQuerySpace; import org.hibernate.loader.plan2.build.spi.ExpandingEntityQuerySpace; -import org.hibernate.loader.plan2.spi.EntityQuerySpace; import org.hibernate.loader.plan2.spi.Join; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.PropertyMapping; import org.hibernate.persister.entity.Queryable; -import org.hibernate.persister.walking.spi.AssociationAttributeDefinition; import org.hibernate.persister.walking.spi.AttributeDefinition; import org.hibernate.persister.walking.spi.CompositionDefinition; import org.hibernate.type.AssociationType; @@ -43,7 +41,7 @@ import org.hibernate.type.EntityType; /** * @author Steve Ebersole */ -public class EntityQuerySpaceImpl extends AbstractQuerySpace implements ExpandingEntityQuerySpace, EntityQuerySpace { +public class EntityQuerySpaceImpl extends AbstractQuerySpace implements ExpandingEntityQuerySpace { private final EntityPersister persister; public EntityQuerySpaceImpl( diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/spaces/QuerySpacesImpl.java b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/spaces/QuerySpacesImpl.java index abc3e5d489..e162f4c806 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/spaces/QuerySpacesImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/internal/spaces/QuerySpacesImpl.java @@ -32,9 +32,9 @@ import org.jboss.logging.Logger; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.internal.CoreLogging; +import org.hibernate.loader.plan2.build.spi.ExpandingEntityQuerySpace; import org.hibernate.loader.plan2.build.spi.ExpandingQuerySpaces; import org.hibernate.loader.plan2.spi.CollectionQuerySpace; -import org.hibernate.loader.plan2.spi.EntityQuerySpace; import org.hibernate.loader.plan2.spi.QuerySpace; import org.hibernate.loader.plan2.spi.QuerySpaceUidNotRegisteredException; import org.hibernate.persister.collection.CollectionPersister; @@ -86,7 +86,7 @@ public class QuerySpacesImpl implements ExpandingQuerySpaces { } @Override - public EntityQuerySpace makeEntityQuerySpace(String uid, EntityPersister entityPersister) { + public ExpandingEntityQuerySpace makeEntityQuerySpace(String uid, EntityPersister entityPersister) { if ( querySpaceByUid.containsKey( uid ) ) { throw new IllegalStateException( "Encountered duplicate QuerySpace uid : " + uid ); } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/spi/AbstractLoadPlanBuildingAssociationVisitationStrategy.java b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/spi/AbstractLoadPlanBuildingAssociationVisitationStrategy.java index e2c5691015..a2f5e78005 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/spi/AbstractLoadPlanBuildingAssociationVisitationStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/spi/AbstractLoadPlanBuildingAssociationVisitationStrategy.java @@ -599,7 +599,7 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy // it must be loaded when the ID for the dependent entity is resolved. Is there some other way to // deal with this??? if ( ! associationKey.equals( currentEntityReferenceAssociationKey ) ) { - currentSource().buildBidirectionalEntityFetch( + currentSource().buildBidirectionalEntityReference( attributeDefinition, fetchStrategy, registeredFetchSource( associationKey ).resolveEntityReference(), diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/spi/ExpandingCompositeQuerySpace.java b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/spi/ExpandingCompositeQuerySpace.java new file mode 100644 index 0000000000..9bf2599610 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/spi/ExpandingCompositeQuerySpace.java @@ -0,0 +1,32 @@ +/* + * 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.plan2.build.spi; + +import org.hibernate.loader.plan2.spi.CompositeQuerySpace; + +/** + * @author Gail Badner + */ +public interface ExpandingCompositeQuerySpace extends CompositeQuerySpace, ExpandingQuerySpace { +} diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/spi/ExpandingEntityQuerySpace.java b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/spi/ExpandingEntityQuerySpace.java index 8d3b72de52..2d17289259 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/spi/ExpandingEntityQuerySpace.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/spi/ExpandingEntityQuerySpace.java @@ -23,11 +23,12 @@ */ package org.hibernate.loader.plan2.build.spi; +import org.hibernate.loader.plan2.spi.EntityQuerySpace; import org.hibernate.loader.plan2.spi.Join; /** * @author Steve Ebersole */ -public interface ExpandingEntityQuerySpace extends ExpandingQuerySpace { +public interface ExpandingEntityQuerySpace extends EntityQuerySpace, ExpandingQuerySpace { public Join makeCompositeIdentifierJoin(); } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/spi/ExpandingFetchSource.java b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/spi/ExpandingFetchSource.java index 4c16cb4aa3..8efcdc25c9 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/spi/ExpandingFetchSource.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/spi/ExpandingFetchSource.java @@ -24,7 +24,7 @@ package org.hibernate.loader.plan2.build.spi; import org.hibernate.engine.FetchStrategy; -import org.hibernate.loader.plan2.spi.BidirectionalEntityFetch; +import org.hibernate.loader.plan2.spi.BidirectionalEntityReference; import org.hibernate.loader.plan2.spi.CollectionFetch; import org.hibernate.loader.plan2.spi.CompositeFetch; import org.hibernate.loader.plan2.spi.EntityFetch; @@ -54,7 +54,7 @@ public interface ExpandingFetchSource extends FetchSource { FetchStrategy fetchStrategy, LoadPlanBuildingContext loadPlanBuildingContext); - public BidirectionalEntityFetch buildBidirectionalEntityFetch( + public BidirectionalEntityReference buildBidirectionalEntityReference( AssociationAttributeDefinition attributeDefinition, FetchStrategy fetchStrategy, EntityReference targetEntityReference, diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/spi/ExpandingQuerySpaces.java b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/spi/ExpandingQuerySpaces.java index 8b28795f1c..836f12984f 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/spi/ExpandingQuerySpaces.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/spi/ExpandingQuerySpaces.java @@ -24,7 +24,6 @@ package org.hibernate.loader.plan2.build.spi; import org.hibernate.loader.plan2.spi.CollectionQuerySpace; -import org.hibernate.loader.plan2.spi.EntityQuerySpace; import org.hibernate.loader.plan2.spi.QuerySpaces; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; @@ -35,7 +34,7 @@ import org.hibernate.persister.entity.EntityPersister; public interface ExpandingQuerySpaces extends QuerySpaces { public String generateImplicitUid(); - public EntityQuerySpace makeEntityQuerySpace(String uid, EntityPersister entityPersister); + public ExpandingEntityQuerySpace makeEntityQuerySpace(String uid, EntityPersister entityPersister); public CollectionQuerySpace makeCollectionQuerySpace(String uid, CollectionPersister collectionPersister); } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/spi/ReturnGraphTreePrinter.java b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/spi/ReturnGraphTreePrinter.java index 3789e913ae..3721e7c599 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/spi/ReturnGraphTreePrinter.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan2/build/spi/ReturnGraphTreePrinter.java @@ -27,7 +27,7 @@ import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.io.PrintWriter; -import org.hibernate.loader.plan2.spi.BidirectionalEntityFetch; +import org.hibernate.loader.plan2.spi.BidirectionalEntityReference; import org.hibernate.loader.plan2.spi.CollectionFetch; import org.hibernate.loader.plan2.spi.CollectionFetchableElement; import org.hibernate.loader.plan2.spi.CollectionFetchableIndex; @@ -153,7 +153,7 @@ public class ReturnGraphTreePrinter { } private void writeEntityReferenceFetches(EntityReference entityReference, int depth, PrintWriter printWriter) { - if ( BidirectionalEntityFetch.class.isInstance( entityReference ) ) { + if ( BidirectionalEntityReference.class.isInstance( entityReference ) ) { return; } if ( entityReference.getIdentifierDescription().hasFetches() ) { diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan2/exec/process/spi/AbstractRowReader.java b/hibernate-core/src/main/java/org/hibernate/loader/plan2/exec/process/spi/AbstractRowReader.java index 662f35157a..99e79e0a00 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan2/exec/process/spi/AbstractRowReader.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan2/exec/process/spi/AbstractRowReader.java @@ -39,7 +39,7 @@ import org.hibernate.internal.CoreLogging; import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.loader.plan2.exec.process.internal.HydratedEntityRegistration; import org.hibernate.loader.plan2.exec.process.internal.ResultSetProcessingContextImpl; -import org.hibernate.loader.plan2.spi.BidirectionalEntityFetch; +import org.hibernate.loader.plan2.spi.BidirectionalEntityReference; import org.hibernate.loader.plan2.spi.CompositeFetch; import org.hibernate.loader.plan2.spi.EntityFetch; import org.hibernate.loader.plan2.spi.EntityIdentifierDescription; @@ -129,7 +129,7 @@ public abstract class AbstractRowReader implements RowReader { final EntityReference entityReference = entityReferenceInitializer.getEntityReference(); final EntityIdentifierDescription identifierDescription = entityReference.getIdentifierDescription(); - if ( identifierDescription.hasFetches() ) { + if ( identifierDescription.hasFetches() || identifierDescription.hasBidirectionalEntityReferences() ) { resolveEntityKey( resultSet, context, (FetchSource) identifierDescription, initializerByEntityReference ); } entityReferenceInitializer.resolveEntityKey( resultSet, context ); @@ -140,27 +140,31 @@ public abstract class AbstractRowReader implements RowReader { ResultSetProcessingContextImpl context, FetchSource fetchSource, Map initializerByEntityReference) throws SQLException { + // Resolve any bidirectional entity references first. + for ( BidirectionalEntityReference bidirectionalEntityReference : fetchSource.getBidirectionalEntityReferences() ) { + final EntityReferenceInitializer targetEntityReferenceInitializer = initializerByEntityReference.get( + bidirectionalEntityReference.getTargetEntityReference() + ); + resolveEntityKey( + resultSet, + context, + targetEntityReferenceInitializer, + initializerByEntityReference + ); + targetEntityReferenceInitializer.hydrateEntityState( resultSet, context ); + } for ( Fetch fetch : fetchSource.getFetches() ) { if ( EntityFetch.class.isInstance( fetch ) ) { final EntityFetch entityFetch = (EntityFetch) fetch; - final EntityReferenceInitializer targetEntityReferenceInitializer; - if ( BidirectionalEntityFetch.class.isInstance( fetch ) ) { - final BidirectionalEntityFetch bidirectionalEntityFetch = (BidirectionalEntityFetch) fetch; - targetEntityReferenceInitializer = initializerByEntityReference.get( - bidirectionalEntityFetch.getTargetEntityReference() - ); - } - else { - targetEntityReferenceInitializer = initializerByEntityReference.get( entityFetch ); - } - if ( targetEntityReferenceInitializer != null ) { + final EntityReferenceInitializer entityReferenceInitializer = initializerByEntityReference.get( entityFetch ); + if ( entityReferenceInitializer != null ) { resolveEntityKey( resultSet, context, - targetEntityReferenceInitializer, + entityReferenceInitializer, initializerByEntityReference ); - targetEntityReferenceInitializer.hydrateEntityState( resultSet, context ); + entityReferenceInitializer.hydrateEntityState( resultSet, context ); } } else if ( CompositeFetch.class.isInstance( fetch ) ) { diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan2/spi/BidirectionalEntityFetch.java b/hibernate-core/src/main/java/org/hibernate/loader/plan2/spi/BidirectionalEntityReference.java similarity index 97% rename from hibernate-core/src/main/java/org/hibernate/loader/plan2/spi/BidirectionalEntityFetch.java rename to hibernate-core/src/main/java/org/hibernate/loader/plan2/spi/BidirectionalEntityReference.java index 44a8daa188..998abcb134 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan2/spi/BidirectionalEntityFetch.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan2/spi/BidirectionalEntityReference.java @@ -38,7 +38,7 @@ package org.hibernate.loader.plan2.spi; * * @author Steve Ebersole */ -public interface BidirectionalEntityFetch { +public interface BidirectionalEntityReference extends EntityReference { /** * Get the targeted EntityReference * diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan2/spi/EntityIdentifierDescription.java b/hibernate-core/src/main/java/org/hibernate/loader/plan2/spi/EntityIdentifierDescription.java index 8656b089c1..b336bcc91a 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan2/spi/EntityIdentifierDescription.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan2/spi/EntityIdentifierDescription.java @@ -37,4 +37,13 @@ public interface EntityIdentifierDescription { * non-empty results for {@link FetchSource#getFetches()} */ public boolean hasFetches(); + + /** + * Can this EntityIdentifierDescription be treated as a FetchSource and if so does it have any + * bidirectional entity references? + * + * @return {@code true} iff {@code this} can be cast to {@link FetchSource} and (after casting) it returns + * non-empty results for {@link FetchSource#getBidirectionalEntityReferences()} + */ + public boolean hasBidirectionalEntityReferences(); } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan2/spi/FetchSource.java b/hibernate-core/src/main/java/org/hibernate/loader/plan2/spi/FetchSource.java index fbed8bc124..46239961c1 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan2/spi/FetchSource.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan2/spi/FetchSource.java @@ -32,10 +32,6 @@ import org.hibernate.loader.PropertyPath; * @author Steve Ebersole */ public interface FetchSource { - /** - * Convenient constant for returning no fetches from {@link #getFetches()} - */ - public static final Fetch[] NO_FETCHES = new Fetch[0]; /** * Get the property path to this fetch owner @@ -47,12 +43,19 @@ public interface FetchSource { public String getQuerySpaceUid(); /** - * Retrieve the fetches owned by this return. + * Retrieve the fetches owned by this fetch source. * * @return The owned fetches. */ public Fetch[] getFetches(); + /** + * Retrieve the bidirectional entity references owned by this fetch source. + * + * @return The owned bidirectional entity references. + */ + public BidirectionalEntityReference[] getBidirectionalEntityReferences(); + /** * Resolve the "current" {@link EntityReference}, or null if none. * 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 d7b9c3747e..f21e11118b 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 @@ -3792,8 +3792,6 @@ public abstract class AbstractEntityPersister } private void doLateInit() { - generateEntityDefinition(); - //insert/update/delete SQL final int joinSpan = getTableSpan(); sqlDeleteStrings = new String[joinSpan]; @@ -3854,7 +3852,6 @@ public abstract class AbstractEntityPersister public final void postInstantiate() throws MappingException { doLateInit(); -// generateEntityDefinition(); createLoaders(); createUniqueKeyLoaders(); @@ -5120,7 +5117,8 @@ public abstract class AbstractEntityPersister private Iterable embeddedCompositeIdentifierAttributes; private Iterable attributeDefinitions; - protected void generateEntityDefinition() { + @Override + public void generateEntityDefinition() { prepareEntityIdentifierDefinition(); collectAttributeDefinitions(); } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/EntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/EntityPersister.java index d3ca57955e..f29f55fa4e 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/EntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/EntityPersister.java @@ -45,7 +45,6 @@ import org.hibernate.id.IdentifierGenerator; import org.hibernate.internal.FilterAliasGenerator; import org.hibernate.metadata.ClassMetadata; import org.hibernate.persister.walking.spi.EntityDefinition; -import org.hibernate.sql.ordering.antlr.ColumnMapper; import org.hibernate.tuple.entity.EntityMetamodel; import org.hibernate.tuple.entity.EntityTuplizer; import org.hibernate.type.Type; @@ -71,7 +70,14 @@ public interface EntityPersister extends OptimisticCacheSource, EntityDefinition public static final String ENTITY_ID = "id"; /** - * Finish the initialization of this object. + * Generate the entity definition for this object. This must be done for all + * entity persisters before calling {@link #postInstantiate()}. + */ + public void generateEntityDefinition(); + + /** + * Finish the initialization of this object. {@link #generateEntityDefinition()} + * must be called for all entity persisters before calling this method. *

* Called only once per {@link org.hibernate.SessionFactory} lifecycle, * after all entity persisters have been instantiated. 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 deleted file mode 100644 index f9371d0649..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractCompositeBasedAttribute.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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.tuple.component; - -import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.tuple.AbstractNonIdentifierAttribute; -import org.hibernate.tuple.BaselineAttributeInformation; -import org.hibernate.tuple.NonIdentifierAttribute; -import org.hibernate.type.Type; - -/** - * A base class for a sub-attribute of a composite, non-identifier attribute. - * - * @author Steve Ebersole - */ -public abstract class AbstractCompositeBasedAttribute - extends AbstractNonIdentifierAttribute - implements NonIdentifierAttribute { - - private final int ownerAttributeNumber; - - public AbstractCompositeBasedAttribute( - AbstractCompositionAttribute source, - SessionFactoryImplementor sessionFactory, - int attributeNumber, - String attributeName, - Type attributeType, - BaselineAttributeInformation baselineInfo, - int ownerAttributeNumber) { - super( source, sessionFactory, attributeNumber, attributeName, attributeType, baselineInfo ); - this.ownerAttributeNumber = ownerAttributeNumber; - } - - protected int ownerAttributeNumber() { - return ownerAttributeNumber; - } - - @Override - public AbstractCompositionAttribute getSource() { - return (AbstractCompositionAttribute) super.getSource(); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractCompositionAttribute.java b/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractCompositionAttribute.java index a5c6d02f26..245596c48e 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractCompositionAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractCompositionAttribute.java @@ -35,7 +35,6 @@ 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.CompositionDefinition; -import org.hibernate.persister.walking.spi.EntityDefinition; import org.hibernate.tuple.AbstractNonIdentifierAttribute; import org.hibernate.tuple.BaselineAttributeInformation; import org.hibernate.type.AssociationType; @@ -54,14 +53,18 @@ import static org.hibernate.engine.internal.JoinHelper.getRHSColumnNames; */ public abstract class AbstractCompositionAttribute extends AbstractNonIdentifierAttribute implements CompositionDefinition { + private final int columnStartPosition; + protected AbstractCompositionAttribute( AttributeSource source, SessionFactoryImplementor sessionFactory, - int attributeNumber, + int entityBasedAttributeNumber, String attributeName, CompositeType attributeType, + int columnStartPosition, BaselineAttributeInformation baselineInfo) { - super( source, sessionFactory, attributeNumber, attributeName, attributeType, baselineInfo ); + super( source, sessionFactory, entityBasedAttributeNumber, attributeName, attributeType, baselineInfo ); + this.columnStartPosition = columnStartPosition; } @Override @@ -77,7 +80,7 @@ public abstract class AbstractCompositionAttribute extends AbstractNonIdentifier return new Iterator() { private final int numberOfAttributes = getType().getSubtypes().length; private int currentSubAttributeNumber = 0; - private int currentColumnPosition = 0; + private int currentColumnPosition = columnStartPosition; @Override public boolean hasNext() { @@ -106,13 +109,13 @@ public abstract class AbstractCompositionAttribute extends AbstractNonIdentifier JoinHelper.getLHSTableName( aType, attributeNumber(), - (OuterJoinLoadable) getSource() + (OuterJoinLoadable) locateOwningPersister() ), JoinHelper.getLHSColumnNames( aType, attributeNumber(), - 0, - (OuterJoinLoadable) getSource(), + columnPosition, + (OuterJoinLoadable) locateOwningPersister(), sessionFactory() ) ); @@ -129,24 +132,15 @@ public abstract class AbstractCompositionAttribute extends AbstractNonIdentifier else { final OuterJoinLoadable entityPersister = (OuterJoinLoadable) locateOwningPersister(); lhsTableName = getLHSTableName( aType, attributeNumber(), entityPersister ); - lhsColumnNames = getLHSColumnNames( aType, attributeNumber(), entityPersister, sessionFactory() ); + lhsColumnNames = getLHSColumnNames( + aType, + attributeNumber(), + columnPosition, + entityPersister, + sessionFactory() + ); } associationKey = new AssociationKey( lhsTableName, lhsColumnNames ); - -// associationKey = new AssociationKey( -// getLHSTableName( -// aType, -// attributeNumber(), -// (OuterJoinLoadable) locateOwningPersister() -// ), -// getLHSColumnNames( -// aType, -// attributeNumber(), -// columnPosition, -// (OuterJoinLoadable) locateOwningPersister(), -// sessionFactory() -// ) -// ); } else { associationKey = new AssociationKey( @@ -156,12 +150,14 @@ public abstract class AbstractCompositionAttribute extends AbstractNonIdentifier } final CompositeType cType = getType(); - final boolean nullable = cType.getPropertyNullability() == null || cType.getPropertyNullability()[subAttributeNumber]; + final boolean nullable = + cType.getPropertyNullability() == null || + cType.getPropertyNullability()[subAttributeNumber]; return new CompositeBasedAssociationAttribute( AbstractCompositionAttribute.this, sessionFactory(), - subAttributeNumber, + attributeNumber(), name, (AssociationType) type, new BaselineAttributeInformation.Builder() @@ -175,7 +171,7 @@ public abstract class AbstractCompositionAttribute extends AbstractNonIdentifier .setCascadeStyle( getType().getCascadeStyle( subAttributeNumber ) ) .setFetchMode( getType().getFetchMode( subAttributeNumber ) ) .createInformation(), - AbstractCompositionAttribute.this.attributeNumber(), + subAttributeNumber, associationKey ); } @@ -183,9 +179,10 @@ public abstract class AbstractCompositionAttribute extends AbstractNonIdentifier return new CompositionBasedCompositionAttribute( AbstractCompositionAttribute.this, sessionFactory(), - subAttributeNumber, + attributeNumber(), name, (CompositeType) type, + columnPosition, new BaselineAttributeInformation.Builder() .setInsertable( AbstractCompositionAttribute.this.isInsertable() ) .setUpdateable( AbstractCompositionAttribute.this.isUpdateable() ) @@ -233,14 +230,7 @@ public abstract class AbstractCompositionAttribute extends AbstractNonIdentifier }; } - public EntityPersister locateOwningPersister() { - if ( EntityDefinition.class.isInstance( getSource() ) ) { - return ( (EntityDefinition) getSource() ).getEntityPersister(); - } - else { - return ( (AbstractCompositionAttribute) getSource() ).locateOwningPersister(); - } - } + protected abstract EntityPersister locateOwningPersister(); @Override protected String loggableMetadata() { 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 d3d52ecc3c..33af91cac7 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 @@ -43,31 +43,30 @@ import org.hibernate.persister.walking.spi.AssociationKey; import org.hibernate.persister.walking.spi.CollectionDefinition; import org.hibernate.persister.walking.spi.EntityDefinition; import org.hibernate.persister.walking.spi.WalkingException; +import org.hibernate.tuple.AbstractNonIdentifierAttribute; import org.hibernate.tuple.BaselineAttributeInformation; +import org.hibernate.tuple.NonIdentifierAttribute; import org.hibernate.type.AnyType; import org.hibernate.type.AssociationType; -import org.hibernate.type.CompositeType; /** * @author Steve Ebersole */ public class CompositeBasedAssociationAttribute - extends AbstractCompositeBasedAttribute - implements AssociationAttributeDefinition { + extends AbstractNonIdentifierAttribute + implements NonIdentifierAttribute, AssociationAttributeDefinition { + private final int subAttributeNumber; private final AssociationKey associationKey; private Joinable joinable; public CompositeBasedAssociationAttribute( AbstractCompositionAttribute source, SessionFactoryImplementor factory, - int attributeNumber, - String attributeName, - AssociationType attributeType, - BaselineAttributeInformation baselineInfo, - int ownerAttributeNumber, + int entityBasedAttributeNumber, String attributeName, AssociationType attributeType, BaselineAttributeInformation baselineInfo, int subAttributeNumber, AssociationKey associationKey) { - super( source, factory, attributeNumber, attributeName, attributeType, baselineInfo, ownerAttributeNumber ); + super( source, factory, entityBasedAttributeNumber, attributeName, attributeType, baselineInfo ); + this.subAttributeNumber = subAttributeNumber; this.associationKey = associationKey; } @@ -76,6 +75,11 @@ public class CompositeBasedAssociationAttribute return (AssociationType) super.getType(); } + @Override + public AbstractCompositionAttribute getSource() { + return (AbstractCompositionAttribute) super.getSource(); + } + protected Joinable getJoinable() { if ( joinable == null ) { joinable = getType().getAssociatedJoinable( sessionFactory() ); @@ -148,37 +152,21 @@ public class CompositeBasedAssociationAttribute @Override public FetchStrategy determineFetchPlan(LoadQueryInfluencers loadQueryInfluencers, PropertyPath propertyPath) { - final EntityPersister owningPersister = locateOwningPersister(); + final EntityPersister owningPersister = getSource().locateOwningPersister(); - FetchStyle style = determineFetchStyleByProfile( + FetchStyle style = FetchStrategyHelper.determineFetchStyleByProfile( loadQueryInfluencers, owningPersister, propertyPath, - ownerAttributeNumber() + attributeNumber() ); if ( style == null ) { - style = determineFetchStyleByMetadata( - getSource().getType().getFetchMode( attributeNumber() ), - getType() - ); + style = determineFetchStyleByMetadata( getFetchMode(), getType() ); } return new FetchStrategy( determineFetchTiming( style ), style ); } - protected FetchStyle determineFetchStyleByProfile( - LoadQueryInfluencers loadQueryInfluencers, - EntityPersister owningPersister, - PropertyPath propertyPath, - int ownerAttributeNumber) { - return FetchStrategyHelper.determineFetchStyleByProfile( - loadQueryInfluencers, - owningPersister, - propertyPath, - ownerAttributeNumber - ); - } - protected FetchStyle determineFetchStyleByMetadata(FetchMode fetchMode, AssociationType type) { return FetchStrategyHelper.determineFetchStyleByMetadata( fetchMode, type, sessionFactory() ); } @@ -187,14 +175,9 @@ public class CompositeBasedAssociationAttribute return FetchStrategyHelper.determineFetchTiming( style, getType(), sessionFactory() ); } - private EntityPersister locateOwningPersister() { - return getSource().locateOwningPersister(); - } - @Override public CascadeStyle determineCascadeStyle() { - final CompositeType compositeType = (CompositeType) locateOwningPersister().getPropertyType( getName() ); - return compositeType.getCascadeStyle( attributeNumber() ); + return getCascadeStyle(); } private HydratedCompoundValueHandler hydratedCompoundValueHandler; @@ -205,12 +188,12 @@ public class CompositeBasedAssociationAttribute hydratedCompoundValueHandler = new HydratedCompoundValueHandler() { @Override public Object extract(Object hydratedState) { - return ( (Object[] ) hydratedState )[ attributeNumber() ]; + return ( (Object[] ) hydratedState )[ subAttributeNumber ]; } @Override public void inject(Object hydratedState, Object value) { - ( (Object[] ) hydratedState )[ attributeNumber() ] = value; + ( (Object[] ) hydratedState )[ subAttributeNumber ] = value; } }; } 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 6e22bcc44b..fa301ae8da 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 @@ -24,22 +24,43 @@ package org.hibernate.tuple.component; import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.persister.walking.spi.CompositionDefinition; +import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.persister.walking.spi.EntityDefinition; import org.hibernate.tuple.BaselineAttributeInformation; import org.hibernate.type.CompositeType; /** * @author Steve Ebersole */ -public class CompositionBasedCompositionAttribute - extends AbstractCompositionAttribute { +public class CompositionBasedCompositionAttribute extends AbstractCompositionAttribute { + public CompositionBasedCompositionAttribute( - CompositionDefinition source, + AbstractCompositionAttribute source, SessionFactoryImplementor sessionFactory, - int attributeNumber, + int entityBasedAttributeNumber, String attributeName, CompositeType attributeType, + int columnStartPosition, BaselineAttributeInformation baselineInfo) { - super( source, sessionFactory, attributeNumber, attributeName, attributeType, baselineInfo ); + super( + source, + sessionFactory, + entityBasedAttributeNumber, + attributeName, + attributeType, + columnStartPosition, + baselineInfo + ); + } + + @Override + protected EntityPersister locateOwningPersister() { + final AbstractCompositionAttribute source = (AbstractCompositionAttribute) getSource(); + if ( EntityDefinition.class.isInstance( source.getSource() ) ) { + return EntityDefinition.class.cast( source.getSource() ).getEntityPersister(); + } + else { + return AbstractCompositionAttribute.class.cast( source.getSource() ).locateOwningPersister(); + } } } 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 66a7242a5f..8d381067dc 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 @@ -44,6 +44,11 @@ public class EntityBasedCompositionAttribute String attributeName, CompositeType attributeType, BaselineAttributeInformation baselineInfo) { - super( source, factory, attributeNumber, attributeName, attributeType, baselineInfo ); + super( source, factory, attributeNumber, attributeName, attributeType, 0, baselineInfo ); + } + + @Override + protected EntityPersister locateOwningPersister() { + return (EntityPersister) getSource(); } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/cfg/persister/GoofyPersisterClassProvider.java b/hibernate-core/src/test/java/org/hibernate/test/cfg/persister/GoofyPersisterClassProvider.java index ee81885573..ee2766c018 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/cfg/persister/GoofyPersisterClassProvider.java +++ b/hibernate-core/src/test/java/org/hibernate/test/cfg/persister/GoofyPersisterClassProvider.java @@ -115,6 +115,10 @@ public class GoofyPersisterClassProvider implements PersisterClassResolver { return new NonPojoInstrumentationMetadata( null ); } + @Override + public void generateEntityDefinition() { + } + @Override public void postInstantiate() throws MappingException { diff --git a/hibernate-core/src/test/java/org/hibernate/test/legacy/CustomPersister.java b/hibernate-core/src/test/java/org/hibernate/test/legacy/CustomPersister.java index 64553579b4..4333a97774 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/legacy/CustomPersister.java +++ b/hibernate-core/src/test/java/org/hibernate/test/legacy/CustomPersister.java @@ -77,6 +77,10 @@ public class CustomPersister implements EntityPersister { return Custom.class; } + @Override + public void generateEntityDefinition() { + } + public void postInstantiate() throws MappingException {} public String getEntityName() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/loadplans/plans/LoadPlanStructureAssertionTest.java b/hibernate-core/src/test/java/org/hibernate/test/loadplans/plans/LoadPlanStructureAssertionTest.java index 10f2765514..9836b4f79e 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/loadplans/plans/LoadPlanStructureAssertionTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/loadplans/plans/LoadPlanStructureAssertionTest.java @@ -26,7 +26,7 @@ package org.hibernate.test.loadplans.plans; import org.hibernate.cfg.Configuration; import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.loader.plan2.spi.BidirectionalEntityFetch; +import org.hibernate.loader.plan2.spi.BidirectionalEntityReference; import org.hibernate.test.annotations.Country; import org.hibernate.test.annotations.collectionelement.Boy; import org.hibernate.test.annotations.collectionelement.Matrix; @@ -226,18 +226,19 @@ public class LoadPlanStructureAssertionTest extends BaseUnitTestCase { FetchSource.class, cardFieldElementGraph.getIdentifierDescription() ); - assertEquals( 2, cardFieldElementGraphIdAsFetchSource.getFetches().length ); + assertEquals( 1, cardFieldElementGraphIdAsFetchSource.getFetches().length ); + assertEquals( 1, cardFieldElementGraphIdAsFetchSource.getBidirectionalEntityReferences().length ); - BidirectionalEntityFetch circularCardFetch = assertTyping( - BidirectionalEntityFetch.class, - cardFieldElementGraphIdAsFetchSource.getFetches()[0] + BidirectionalEntityReference circularCardFetch = assertTyping( + BidirectionalEntityReference.class, + cardFieldElementGraphIdAsFetchSource.getBidirectionalEntityReferences()[0] ); assertSame( circularCardFetch.getTargetEntityReference(), cardReturn ); // the fetch above is to the other key-many-to-one for CardField.primaryKey composite: key EntityFetch keyFetch = assertTyping( EntityFetch.class, - cardFieldElementGraphIdAsFetchSource.getFetches()[1] + cardFieldElementGraphIdAsFetchSource.getFetches()[0] ); assertEquals( Key.class.getName(), keyFetch.getEntityPersister().getEntityName() ); } diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/ejb3configuration/PersisterClassProviderTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/ejb3configuration/PersisterClassProviderTest.java index c506af986c..771fd6460c 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/ejb3configuration/PersisterClassProviderTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/ejb3configuration/PersisterClassProviderTest.java @@ -143,6 +143,10 @@ public class PersisterClassProviderTest { return new NonPojoInstrumentationMetadata( getEntityName() ); } + @Override + public void generateEntityDefinition() { + } + @Override public void postInstantiate() throws MappingException {