HHH-8276 - Integrate LoadPlans into UniqueEntityLoader (PoC)

This commit is contained in:
Gail Badner 2013-09-23 16:11:27 -07:00 committed by Steve Ebersole
parent 4420fa71d6
commit f111600e1f
40 changed files with 504 additions and 608 deletions

View File

@ -469,6 +469,10 @@ public final class SessionFactoryImpl
); );
// after *all* persisters and named queries are registered // after *all* persisters and named queries are registered
for ( EntityPersister persister : entityPersisters.values() ) {
persister.generateEntityDefinition();
}
for ( EntityPersister persister : entityPersisters.values() ) { for ( EntityPersister persister : entityPersisters.values() ) {
persister.postInstantiate(); persister.postInstantiate();
registerEntityNameResolvers( persister ); registerEntityNameResolvers( persister );

View File

@ -23,16 +23,11 @@
*/ */
package org.hibernate.loader.plan2.build.internal.returns; package org.hibernate.loader.plan2.build.internal.returns;
import org.hibernate.engine.FetchStrategy;
import org.hibernate.loader.PropertyPath; 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.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.EntityReference;
import org.hibernate.loader.plan2.spi.FetchSource; 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; import org.hibernate.type.CompositeType;
/** /**
@ -47,7 +42,7 @@ public abstract class AbstractCompositeEntityIdentifierDescription
protected AbstractCompositeEntityIdentifierDescription( protected AbstractCompositeEntityIdentifierDescription(
EntityReference entityReference, EntityReference entityReference,
CompositeQuerySpace compositeQuerySpace, ExpandingCompositeQuerySpace compositeQuerySpace,
CompositeType identifierType, CompositeType identifierType,
PropertyPath propertyPath) { PropertyPath propertyPath) {
super( identifierType, compositeQuerySpace, false, propertyPath ); super( identifierType, compositeQuerySpace, false, propertyPath );
@ -59,6 +54,11 @@ public abstract class AbstractCompositeEntityIdentifierDescription
return getFetches().length > 0; return getFetches().length > 0;
} }
@Override
public boolean hasBidirectionalEntityReferences() {
return getBidirectionalEntityReferences().length > 0;
}
@Override @Override
public FetchSource getSource() { public FetchSource getSource() {
// the source for this (as a Fetch) is the entity reference // the source for this (as a Fetch) is the entity reference

View File

@ -23,63 +23,40 @@
*/ */
package org.hibernate.loader.plan2.build.internal.returns; 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.FetchStrategy;
import org.hibernate.engine.FetchStyle; import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.FetchTiming; import org.hibernate.engine.FetchTiming;
import org.hibernate.loader.PropertyPath; import org.hibernate.loader.PropertyPath;
import org.hibernate.loader.plan2.build.spi.ExpandingFetchSource; import org.hibernate.loader.plan2.build.spi.ExpandingCompositeQuerySpace;
import org.hibernate.loader.plan2.build.spi.ExpandingQuerySpace;
import org.hibernate.loader.plan2.build.spi.LoadPlanBuildingContext; import org.hibernate.loader.plan2.build.spi.LoadPlanBuildingContext;
import org.hibernate.loader.plan2.spi.BidirectionalEntityFetch;
import org.hibernate.loader.plan2.spi.CollectionFetch; import org.hibernate.loader.plan2.spi.CollectionFetch;
import org.hibernate.loader.plan2.spi.CompositeFetch; import org.hibernate.loader.plan2.spi.CompositeFetch;
import org.hibernate.loader.plan2.spi.CompositeQuerySpace;
import org.hibernate.loader.plan2.spi.EntityFetch;
import org.hibernate.loader.plan2.spi.EntityReference; 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.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.AssociationAttributeDefinition;
import org.hibernate.persister.walking.spi.AttributeDefinition; import org.hibernate.persister.walking.spi.AttributeDefinition;
import org.hibernate.persister.walking.spi.CompositionDefinition;
import org.hibernate.persister.walking.spi.WalkingException; import org.hibernate.persister.walking.spi.WalkingException;
import org.hibernate.type.CollectionType;
import org.hibernate.type.CompositeType; import org.hibernate.type.CompositeType;
import org.hibernate.type.EntityType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
* @author Gail Badner * @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 static final FetchStrategy FETCH_STRATEGY = new FetchStrategy( FetchTiming.IMMEDIATE, FetchStyle.JOIN );
private final CompositeType compositeType; private final CompositeType compositeType;
private final CompositeQuerySpace compositeQuerySpace;
private final PropertyPath propertyPath;
private final boolean allowCollectionFetches; private final boolean allowCollectionFetches;
private List<Fetch> fetches;
protected AbstractCompositeFetch( protected AbstractCompositeFetch(
CompositeType compositeType, CompositeType compositeType,
CompositeQuerySpace compositeQuerySpace, ExpandingCompositeQuerySpace compositeQuerySpace,
boolean allowCollectionFetches, PropertyPath propertyPath) { boolean allowCollectionFetches,
PropertyPath propertyPath) {
super( compositeQuerySpace, propertyPath );
this.compositeType = compositeType; this.compositeType = compositeType;
this.compositeQuerySpace = compositeQuerySpace;
this.allowCollectionFetches = allowCollectionFetches; this.allowCollectionFetches = allowCollectionFetches;
this.propertyPath = propertyPath;
}
@SuppressWarnings("UnusedParameters")
protected CompositeQuerySpace resolveCompositeQuerySpace(LoadPlanBuildingContext loadPlanBuildingContext) {
return compositeQuerySpace;
} }
@Override @Override
@ -106,101 +83,21 @@ public abstract class AbstractCompositeFetch implements CompositeFetch, Expandin
); );
} }
@Override
public String getQuerySpaceUid() {
return compositeQuerySpace.getUid();
}
@Override @Override
public void validateFetchPlan(FetchStrategy fetchStrategy, AttributeDefinition attributeDefinition) { public void validateFetchPlan(FetchStrategy fetchStrategy, AttributeDefinition attributeDefinition) {
// anything to do here? // anything to do here?
} }
@Override protected CompositeFetch createCompositeFetch(
public EntityFetch buildEntityFetch( CompositeType compositeType,
AssociationAttributeDefinition attributeDefinition, ExpandingCompositeQuerySpace compositeQuerySpace) {
FetchStrategy fetchStrategy, return new NestedCompositeFetchImpl(
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<Fetch>();
}
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(
this, this,
attributeDefinition.getType(), compositeType,
(CompositeQuerySpace) join.getRightHandSide(), compositeQuerySpace,
allowCollectionFetches, allowCollectionFetches,
getPropertyPath() getPropertyPath()
); );
addFetch( fetch );
return fetch;
} }
@Override @Override
@ -212,50 +109,11 @@ public abstract class AbstractCompositeFetch implements CompositeFetch, Expandin
throw new WalkingException( throw new WalkingException(
String.format( String.format(
"This composite path [%s] does not allow collection fetches (composite id or composite collection index/element", "This composite path [%s] does not allow collection fetches (composite id or composite collection index/element",
propertyPath.getFullPath() getPropertyPath().getFullPath()
) )
); );
} }
return super.buildCollectionFetch( attributeDefinition, fetchStrategy, 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;
}
@Override
public PropertyPath getPropertyPath() {
return propertyPath;
} }
@Override @Override
@ -278,12 +136,6 @@ public abstract class AbstractCompositeFetch implements CompositeFetch, Expandin
return null; 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 // this is being removed to be more ogm/search friendly
@Override @Override
public String[] toSqlSelectFragments(String alias) { public String[] toSqlSelectFragments(String alias) {

View File

@ -23,56 +23,36 @@
*/ */
package org.hibernate.loader.plan2.build.internal.returns; 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.PropertyPath;
import org.hibernate.loader.plan2.build.spi.ExpandingCompositeQuerySpace;
import org.hibernate.loader.plan2.build.spi.ExpandingEntityQuerySpace; 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.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.EntityIdentifierDescription;
import org.hibernate.loader.plan2.spi.EntityQuerySpace;
import org.hibernate.loader.plan2.spi.EntityReference; import org.hibernate.loader.plan2.spi.EntityReference;
import org.hibernate.loader.plan2.spi.Fetch;
import org.hibernate.loader.plan2.spi.Join; import org.hibernate.loader.plan2.spi.Join;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister; 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.EncapsulatedEntityIdentifierDefinition;
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition; 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.CompositeType;
import org.hibernate.type.EntityType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public abstract class AbstractEntityReference implements EntityReference, ExpandingFetchSource { public abstract class AbstractEntityReference extends AbstractExpandingFetchSource implements EntityReference {
private final EntityQuerySpace entityQuerySpace;
private final PropertyPath propertyPath;
private final EntityIdentifierDescription identifierDescription; private final EntityIdentifierDescription identifierDescription;
private List<Fetch> fetches;
public AbstractEntityReference( public AbstractEntityReference(
EntityQuerySpace entityQuerySpace, ExpandingEntityQuerySpace entityQuerySpace,
PropertyPath propertyPath) { PropertyPath propertyPath) {
this.entityQuerySpace = entityQuerySpace; super( entityQuerySpace, propertyPath );
this.propertyPath = propertyPath;
this.identifierDescription = buildIdentifierDescription(); 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, * 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 * @return the descriptor for the identifier
*/ */
private EntityIdentifierDescription buildIdentifierDescription() { private EntityIdentifierDescription buildIdentifierDescription() {
final EntityPersister persister = entityQuerySpace.getEntityPersister(); final EntityIdentifierDefinition identifierDefinition = getEntityPersister().getEntityKeyDefinition();
final EntityIdentifierDefinition identifierDefinition = persister.getEntityKeyDefinition();
if ( identifierDefinition.isEncapsulated() ) { if ( identifierDefinition.isEncapsulated() ) {
final EncapsulatedEntityIdentifierDefinition encapsulatedIdentifierDefinition = (EncapsulatedEntityIdentifierDefinition) identifierDefinition; 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... // 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() return identifierDefinition.isEncapsulated()
? buildEncapsulatedCompositeIdentifierDescription( join ) ? buildEncapsulatedCompositeIdentifierDescription( join )
: buildNonEncapsulatedCompositeIdentifierDescription( join ); : buildNonEncapsulatedCompositeIdentifierDescription( join );
@ -102,18 +81,18 @@ public abstract class AbstractEntityReference implements EntityReference, Expand
private NonEncapsulatedEntityIdentifierDescription buildNonEncapsulatedCompositeIdentifierDescription(Join compositeJoin) { private NonEncapsulatedEntityIdentifierDescription buildNonEncapsulatedCompositeIdentifierDescription(Join compositeJoin) {
return new NonEncapsulatedEntityIdentifierDescription( return new NonEncapsulatedEntityIdentifierDescription(
this, this,
(CompositeQuerySpace) compositeJoin.getRightHandSide(), (ExpandingCompositeQuerySpace) compositeJoin.getRightHandSide(),
(CompositeType) entityQuerySpace.getEntityPersister().getIdentifierType(), (CompositeType) getEntityPersister().getIdentifierType(),
propertyPath.append( "id" ) getPropertyPath().append( "id" )
); );
} }
private EncapsulatedEntityIdentifierDescription buildEncapsulatedCompositeIdentifierDescription(Join compositeJoin) { private EncapsulatedEntityIdentifierDescription buildEncapsulatedCompositeIdentifierDescription(Join compositeJoin) {
return new EncapsulatedEntityIdentifierDescription( return new EncapsulatedEntityIdentifierDescription(
this, this,
(CompositeQuerySpace) compositeJoin.getRightHandSide(), (ExpandingCompositeQuerySpace) compositeJoin.getRightHandSide(),
(CompositeType) entityQuerySpace.getEntityPersister().getIdentifierType(), (CompositeType) getEntityPersister().getIdentifierType(),
propertyPath.append( "id" ) getPropertyPath().append( "id" )
); );
} }
@ -122,18 +101,9 @@ public abstract class AbstractEntityReference implements EntityReference, Expand
return this; return this;
} }
protected EntityQuerySpace getEntityQuerySpace() {
return entityQuerySpace;
}
@Override
public String getQuerySpaceUid() {
return getEntityQuerySpace().getUid();
}
@Override @Override
public EntityPersister getEntityPersister() { public EntityPersister getEntityPersister() {
return entityQuerySpace.getEntityPersister(); return expandingEntityQuerySpace().getEntityPersister();
} }
@Override @Override
@ -141,141 +111,15 @@ public abstract class AbstractEntityReference implements EntityReference, Expand
return identifierDescription; return identifierDescription;
} }
@Override protected CompositeFetch createCompositeFetch(
public PropertyPath getPropertyPath() { CompositeType compositeType,
return propertyPath; ExpandingCompositeQuerySpace compositeQuerySpace) {
} return new CompositeFetchImpl(
@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<Fetch>();
}
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(
this, this,
attributeDefinition.getType(), compositeType,
(CompositeQuerySpace) join.getRightHandSide(), compositeQuerySpace,
true, true,
getPropertyPath() 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;
} }
} }

View File

@ -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<Fetch> fetches;
private List<BidirectionalEntityReference> 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<Fetch>();
}
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<BidirectionalEntityReference>();
}
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;
}
}

View File

@ -23,18 +23,15 @@
*/ */
package org.hibernate.loader.plan2.build.internal.returns; package org.hibernate.loader.plan2.build.internal.returns;
import org.hibernate.engine.FetchStrategy;
import org.hibernate.loader.PropertyPath; import org.hibernate.loader.PropertyPath;
import org.hibernate.loader.plan2.build.spi.ExpandingFetchSource; import org.hibernate.loader.plan2.build.spi.ExpandingFetchSource;
import org.hibernate.loader.plan2.spi.BidirectionalEntityFetch; import org.hibernate.loader.plan2.spi.BidirectionalEntityReference;
import org.hibernate.loader.plan2.spi.EntityFetch;
import org.hibernate.loader.plan2.spi.EntityIdentifierDescription; import org.hibernate.loader.plan2.spi.EntityIdentifierDescription;
import org.hibernate.loader.plan2.spi.EntityReference; import org.hibernate.loader.plan2.spi.EntityReference;
import org.hibernate.loader.plan2.spi.Fetch; import org.hibernate.loader.plan2.spi.Fetch;
import org.hibernate.loader.plan2.spi.FetchSource; import org.hibernate.loader.plan2.spi.FetchSource;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition; import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
import org.hibernate.type.EntityType;
/** /**
* Represents an entity fetch that is bi-directionally join fetched. * Represents an entity fetch that is bi-directionally join fetched.
@ -45,21 +42,14 @@ import org.hibernate.type.EntityType;
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class BidirectionalEntityFetchImpl implements BidirectionalEntityFetch, EntityFetch { public class BidirectionalEntityReferenceImpl implements BidirectionalEntityReference {
private final ExpandingFetchSource fetchSource;
private final AssociationAttributeDefinition fetchedAttribute;
private final FetchStrategy fetchStrategy;
private final EntityReference targetEntityReference; private final EntityReference targetEntityReference;
private final PropertyPath propertyPath; private final PropertyPath propertyPath;
public BidirectionalEntityFetchImpl( public BidirectionalEntityReferenceImpl(
ExpandingFetchSource fetchSource, ExpandingFetchSource fetchSource,
AssociationAttributeDefinition fetchedAttribute, AssociationAttributeDefinition fetchedAttribute,
FetchStrategy fetchStrategy,
EntityReference targetEntityReference) { EntityReference targetEntityReference) {
this.fetchSource = fetchSource;
this.fetchedAttribute = fetchedAttribute;
this.fetchStrategy = fetchStrategy;
this.targetEntityReference = targetEntityReference; this.targetEntityReference = targetEntityReference;
this.propertyPath = fetchSource.getPropertyPath().append( fetchedAttribute.getName() ); this.propertyPath = fetchSource.getPropertyPath().append( fetchedAttribute.getName() );
} }
@ -68,41 +58,11 @@ public class BidirectionalEntityFetchImpl implements BidirectionalEntityFetch, E
return targetEntityReference; return targetEntityReference;
} }
@Override
public FetchSource getSource() {
return fetchSource;
}
@Override @Override
public PropertyPath getPropertyPath() { public PropertyPath getPropertyPath() {
return propertyPath; 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 @Override
public String getQuerySpaceUid() { public String getQuerySpaceUid() {
return targetEntityReference.getQuerySpaceUid(); return targetEntityReference.getQuerySpaceUid();
@ -110,7 +70,12 @@ public class BidirectionalEntityFetchImpl implements BidirectionalEntityFetch, E
@Override @Override
public Fetch[] getFetches() { public Fetch[] getFetches() {
return FetchSource.NO_FETCHES; return targetEntityReference.getFetches();
}
@Override
public BidirectionalEntityReference[] getBidirectionalEntityReferences() {
return targetEntityReference.getBidirectionalEntityReferences();
} }
@Override @Override

View File

@ -23,10 +23,10 @@
*/ */
package org.hibernate.loader.plan2.build.internal.returns; 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.CollectionFetchableElement;
import org.hibernate.loader.plan2.spi.CollectionReference; import org.hibernate.loader.plan2.spi.CollectionReference;
import org.hibernate.loader.plan2.spi.CompositeFetch; import org.hibernate.loader.plan2.spi.CompositeFetch;
import org.hibernate.loader.plan2.spi.CompositeQuerySpace;
import org.hibernate.loader.plan2.spi.FetchSource; import org.hibernate.loader.plan2.spi.FetchSource;
import org.hibernate.loader.plan2.spi.Join; import org.hibernate.loader.plan2.spi.Join;
import org.hibernate.type.CompositeType; import org.hibernate.type.CompositeType;
@ -45,7 +45,7 @@ public class CollectionFetchableElementCompositeGraph
public CollectionFetchableElementCompositeGraph(CollectionReference collectionReference, Join compositeJoin) { public CollectionFetchableElementCompositeGraph(CollectionReference collectionReference, Join compositeJoin) {
super( super(
(CompositeType) compositeJoin.getRightHandSide().getPropertyMapping().getType(), (CompositeType) compositeJoin.getRightHandSide().getPropertyMapping().getType(),
(CompositeQuerySpace) compositeJoin.getRightHandSide(), (ExpandingCompositeQuerySpace) compositeJoin.getRightHandSide(),
false, false,
// these property paths are just informational... // these property paths are just informational...
collectionReference.getPropertyPath().append( "<element>" ) collectionReference.getPropertyPath().append( "<element>" )

View File

@ -24,6 +24,7 @@
package org.hibernate.loader.plan2.build.internal.returns; package org.hibernate.loader.plan2.build.internal.returns;
import org.hibernate.engine.FetchStrategy; 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.CollectionFetchableElement;
import org.hibernate.loader.plan2.spi.CollectionReference; import org.hibernate.loader.plan2.spi.CollectionReference;
import org.hibernate.loader.plan2.spi.EntityQuerySpace; import org.hibernate.loader.plan2.spi.EntityQuerySpace;
@ -41,7 +42,7 @@ public class CollectionFetchableElementEntityGraph extends AbstractEntityReferen
CollectionReference collectionReference, CollectionReference collectionReference,
Join entityJoin) { Join entityJoin) {
super( super(
(EntityQuerySpace) entityJoin.getRightHandSide(), (ExpandingEntityQuerySpace) entityJoin.getRightHandSide(),
collectionReference.getPropertyPath().append( "<elements>" ) collectionReference.getPropertyPath().append( "<elements>" )
); );
@ -49,11 +50,6 @@ public class CollectionFetchableElementEntityGraph extends AbstractEntityReferen
this.entityQuerySpace = (EntityQuerySpace) entityJoin.getRightHandSide(); this.entityQuerySpace = (EntityQuerySpace) entityJoin.getRightHandSide();
} }
@Override
protected EntityQuerySpace getEntityQuerySpace() {
return entityQuerySpace;
}
@Override @Override
public CollectionReference getCollectionReference() { public CollectionReference getCollectionReference() {
return collectionReference; return collectionReference;

View File

@ -23,10 +23,10 @@
*/ */
package org.hibernate.loader.plan2.build.internal.returns; 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.CollectionFetchableIndex;
import org.hibernate.loader.plan2.spi.CollectionReference; import org.hibernate.loader.plan2.spi.CollectionReference;
import org.hibernate.loader.plan2.spi.CompositeFetch; import org.hibernate.loader.plan2.spi.CompositeFetch;
import org.hibernate.loader.plan2.spi.CompositeQuerySpace;
import org.hibernate.loader.plan2.spi.FetchSource; import org.hibernate.loader.plan2.spi.FetchSource;
import org.hibernate.loader.plan2.spi.Join; import org.hibernate.loader.plan2.spi.Join;
import org.hibernate.type.CompositeType; import org.hibernate.type.CompositeType;
@ -49,7 +49,7 @@ public class CollectionFetchableIndexCompositeGraph
Join compositeJoin) { Join compositeJoin) {
super( super(
extractIndexType( compositeJoin ), extractIndexType( compositeJoin ),
(CompositeQuerySpace) compositeJoin.getRightHandSide(), (ExpandingCompositeQuerySpace) compositeJoin.getRightHandSide(),
false, false,
collectionReference.getPropertyPath().append( "<index>" ) collectionReference.getPropertyPath().append( "<index>" )
); );

View File

@ -24,6 +24,7 @@
package org.hibernate.loader.plan2.build.internal.returns; package org.hibernate.loader.plan2.build.internal.returns;
import org.hibernate.engine.FetchStrategy; 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.CollectionFetchableIndex;
import org.hibernate.loader.plan2.spi.CollectionReference; import org.hibernate.loader.plan2.spi.CollectionReference;
import org.hibernate.loader.plan2.spi.EntityQuerySpace; import org.hibernate.loader.plan2.spi.EntityQuerySpace;
@ -41,7 +42,7 @@ public class CollectionFetchableIndexEntityGraph extends AbstractEntityReference
CollectionReference collectionReference, CollectionReference collectionReference,
Join entityJoin) { Join entityJoin) {
super( super(
(EntityQuerySpace) entityJoin.getRightHandSide(), (ExpandingEntityQuerySpace) entityJoin.getRightHandSide(),
collectionReference.getPropertyPath().append( "<index>" ) collectionReference.getPropertyPath().append( "<index>" )
); );
@ -54,11 +55,6 @@ public class CollectionFetchableIndexEntityGraph extends AbstractEntityReference
return collectionReference; return collectionReference;
} }
@Override
protected EntityQuerySpace getEntityQuerySpace() {
return entityQuerySpace;
}
@Override @Override
public void validateFetchPlan(FetchStrategy fetchStrategy, AttributeDefinition attributeDefinition) { public void validateFetchPlan(FetchStrategy fetchStrategy, AttributeDefinition attributeDefinition) {
} }

View File

@ -24,8 +24,8 @@
package org.hibernate.loader.plan2.build.internal.returns; package org.hibernate.loader.plan2.build.internal.returns;
import org.hibernate.loader.PropertyPath; 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.CompositeFetch;
import org.hibernate.loader.plan2.spi.CompositeQuerySpace;
import org.hibernate.loader.plan2.spi.FetchSource; import org.hibernate.loader.plan2.spi.FetchSource;
import org.hibernate.type.CompositeType; import org.hibernate.type.CompositeType;
@ -38,7 +38,7 @@ public class CompositeFetchImpl extends AbstractCompositeFetch implements Compos
protected CompositeFetchImpl( protected CompositeFetchImpl(
FetchSource source, FetchSource source,
CompositeType compositeType, CompositeType compositeType,
CompositeQuerySpace compositeQuerySpace, ExpandingCompositeQuerySpace compositeQuerySpace,
boolean allowCollectionFetches, boolean allowCollectionFetches,
PropertyPath propertyPath) { PropertyPath propertyPath) {
super( compositeType, compositeQuerySpace, allowCollectionFetches, propertyPath ); super( compositeType, compositeQuerySpace, allowCollectionFetches, propertyPath );

View File

@ -24,6 +24,7 @@
package org.hibernate.loader.plan2.build.internal.returns; package org.hibernate.loader.plan2.build.internal.returns;
import org.hibernate.loader.PropertyPath; 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.ExpandingEntityIdentifierDescription;
import org.hibernate.loader.plan2.spi.CompositeQuerySpace; import org.hibernate.loader.plan2.spi.CompositeQuerySpace;
import org.hibernate.loader.plan2.spi.EntityReference; import org.hibernate.loader.plan2.spi.EntityReference;
@ -49,7 +50,7 @@ public class EncapsulatedEntityIdentifierDescription
*/ */
protected EncapsulatedEntityIdentifierDescription( protected EncapsulatedEntityIdentifierDescription(
EntityReference entityReference, EntityReference entityReference,
CompositeQuerySpace compositeQuerySpace, ExpandingCompositeQuerySpace compositeQuerySpace,
CompositeType compositeType, CompositeType compositeType,
PropertyPath propertyPath) { PropertyPath propertyPath) {
super( entityReference, compositeQuerySpace, compositeType, propertyPath ); super( entityReference, compositeQuerySpace, compositeType, propertyPath );

View File

@ -24,14 +24,13 @@
package org.hibernate.loader.plan2.build.internal.returns; package org.hibernate.loader.plan2.build.internal.returns;
import org.hibernate.engine.FetchStrategy; 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.build.spi.ExpandingFetchSource;
import org.hibernate.loader.plan2.spi.EntityFetch; 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.FetchSource;
import org.hibernate.loader.plan2.spi.Join; import org.hibernate.loader.plan2.spi.Join;
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition; import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
import org.hibernate.persister.walking.spi.AttributeDefinition; import org.hibernate.persister.walking.spi.AttributeDefinition;
import org.hibernate.persister.walking.spi.WalkingException;
import org.hibernate.type.EntityType; import org.hibernate.type.EntityType;
/** /**
@ -48,7 +47,7 @@ public class EntityFetchImpl extends AbstractEntityReference implements EntityFe
FetchStrategy fetchStrategy, FetchStrategy fetchStrategy,
Join fetchedJoin) { Join fetchedJoin) {
super( super(
(EntityQuerySpace) fetchedJoin.getRightHandSide(), (ExpandingEntityQuerySpace) fetchedJoin.getRightHandSide(),
fetchSource.getPropertyPath().append( fetchedAttribute.getName() ) fetchSource.getPropertyPath().append( fetchedAttribute.getName() )
); );

View File

@ -24,8 +24,8 @@
package org.hibernate.loader.plan2.build.internal.returns; package org.hibernate.loader.plan2.build.internal.returns;
import org.hibernate.loader.PropertyPath; 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.CompositeFetch;
import org.hibernate.loader.plan2.spi.CompositeQuerySpace;
import org.hibernate.loader.plan2.spi.FetchSource; import org.hibernate.loader.plan2.spi.FetchSource;
import org.hibernate.type.CompositeType; import org.hibernate.type.CompositeType;
@ -38,7 +38,7 @@ public class NestedCompositeFetchImpl extends AbstractCompositeFetch {
public NestedCompositeFetchImpl( public NestedCompositeFetchImpl(
CompositeFetch source, CompositeFetch source,
CompositeType type, CompositeType type,
CompositeQuerySpace compositeQuerySpace, ExpandingCompositeQuerySpace compositeQuerySpace,
boolean allowCollectionFetches, PropertyPath propertyPath) { boolean allowCollectionFetches, PropertyPath propertyPath) {
super( type, compositeQuerySpace, allowCollectionFetches, propertyPath ); super( type, compositeQuerySpace, allowCollectionFetches, propertyPath );
this.source = source; this.source = source;

View File

@ -24,7 +24,7 @@
package org.hibernate.loader.plan2.build.internal.returns; package org.hibernate.loader.plan2.build.internal.returns;
import org.hibernate.loader.PropertyPath; 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.loader.plan2.spi.EntityReference;
import org.hibernate.type.CompositeType; import org.hibernate.type.CompositeType;
@ -45,7 +45,7 @@ public class NonEncapsulatedEntityIdentifierDescription extends AbstractComposit
*/ */
public NonEncapsulatedEntityIdentifierDescription( public NonEncapsulatedEntityIdentifierDescription(
EntityReference entityReference, EntityReference entityReference,
CompositeQuerySpace compositeQuerySpace, ExpandingCompositeQuerySpace compositeQuerySpace,
CompositeType compositeType, CompositeType compositeType,
PropertyPath propertyPath) { PropertyPath propertyPath) {
super( super(

View File

@ -33,4 +33,9 @@ public class SimpleEntityIdentifierDescriptionImpl implements EntityIdentifierDe
public boolean hasFetches() { public boolean hasFetches() {
return false; return false;
} }
@Override
public boolean hasBidirectionalEntityReferences() {
return false;
}
} }

View File

@ -25,8 +25,7 @@ package org.hibernate.loader.plan2.build.internal.spaces;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.plan2.build.spi.AbstractQuerySpace; import org.hibernate.loader.plan2.build.spi.AbstractQuerySpace;
import org.hibernate.loader.plan2.build.spi.ExpandingQuerySpace; import org.hibernate.loader.plan2.build.spi.ExpandingCompositeQuerySpace;
import org.hibernate.loader.plan2.spi.CompositeQuerySpace;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.PropertyMapping; import org.hibernate.persister.entity.PropertyMapping;
@ -40,7 +39,7 @@ import org.hibernate.type.EntityType;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class CompositeQuerySpaceImpl extends AbstractQuerySpace implements CompositeQuerySpace, ExpandingQuerySpace { public class CompositeQuerySpaceImpl extends AbstractQuerySpace implements ExpandingCompositeQuerySpace {
private final CompositePropertyMapping compositeSubPropertyMapping; private final CompositePropertyMapping compositeSubPropertyMapping;
public CompositeQuerySpaceImpl( public CompositeQuerySpaceImpl(

View File

@ -26,13 +26,11 @@ package org.hibernate.loader.plan2.build.internal.spaces;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.plan2.build.spi.AbstractQuerySpace; import org.hibernate.loader.plan2.build.spi.AbstractQuerySpace;
import org.hibernate.loader.plan2.build.spi.ExpandingEntityQuerySpace; 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.loader.plan2.spi.Join;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.PropertyMapping; import org.hibernate.persister.entity.PropertyMapping;
import org.hibernate.persister.entity.Queryable; 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.AttributeDefinition;
import org.hibernate.persister.walking.spi.CompositionDefinition; import org.hibernate.persister.walking.spi.CompositionDefinition;
import org.hibernate.type.AssociationType; import org.hibernate.type.AssociationType;
@ -43,7 +41,7 @@ import org.hibernate.type.EntityType;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class EntityQuerySpaceImpl extends AbstractQuerySpace implements ExpandingEntityQuerySpace, EntityQuerySpace { public class EntityQuerySpaceImpl extends AbstractQuerySpace implements ExpandingEntityQuerySpace {
private final EntityPersister persister; private final EntityPersister persister;
public EntityQuerySpaceImpl( public EntityQuerySpaceImpl(

View File

@ -32,9 +32,9 @@ import org.jboss.logging.Logger;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.CoreLogging; 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.build.spi.ExpandingQuerySpaces;
import org.hibernate.loader.plan2.spi.CollectionQuerySpace; 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.QuerySpace;
import org.hibernate.loader.plan2.spi.QuerySpaceUidNotRegisteredException; import org.hibernate.loader.plan2.spi.QuerySpaceUidNotRegisteredException;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
@ -86,7 +86,7 @@ public class QuerySpacesImpl implements ExpandingQuerySpaces {
} }
@Override @Override
public EntityQuerySpace makeEntityQuerySpace(String uid, EntityPersister entityPersister) { public ExpandingEntityQuerySpace makeEntityQuerySpace(String uid, EntityPersister entityPersister) {
if ( querySpaceByUid.containsKey( uid ) ) { if ( querySpaceByUid.containsKey( uid ) ) {
throw new IllegalStateException( "Encountered duplicate QuerySpace uid : " + uid ); throw new IllegalStateException( "Encountered duplicate QuerySpace uid : " + uid );
} }

View File

@ -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 // it must be loaded when the ID for the dependent entity is resolved. Is there some other way to
// deal with this??? // deal with this???
if ( ! associationKey.equals( currentEntityReferenceAssociationKey ) ) { if ( ! associationKey.equals( currentEntityReferenceAssociationKey ) ) {
currentSource().buildBidirectionalEntityFetch( currentSource().buildBidirectionalEntityReference(
attributeDefinition, attributeDefinition,
fetchStrategy, fetchStrategy,
registeredFetchSource( associationKey ).resolveEntityReference(), registeredFetchSource( associationKey ).resolveEntityReference(),

View File

@ -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 {
}

View File

@ -23,11 +23,12 @@
*/ */
package org.hibernate.loader.plan2.build.spi; package org.hibernate.loader.plan2.build.spi;
import org.hibernate.loader.plan2.spi.EntityQuerySpace;
import org.hibernate.loader.plan2.spi.Join; import org.hibernate.loader.plan2.spi.Join;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface ExpandingEntityQuerySpace extends ExpandingQuerySpace { public interface ExpandingEntityQuerySpace extends EntityQuerySpace, ExpandingQuerySpace {
public Join makeCompositeIdentifierJoin(); public Join makeCompositeIdentifierJoin();
} }

View File

@ -24,7 +24,7 @@
package org.hibernate.loader.plan2.build.spi; package org.hibernate.loader.plan2.build.spi;
import org.hibernate.engine.FetchStrategy; 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.CollectionFetch;
import org.hibernate.loader.plan2.spi.CompositeFetch; import org.hibernate.loader.plan2.spi.CompositeFetch;
import org.hibernate.loader.plan2.spi.EntityFetch; import org.hibernate.loader.plan2.spi.EntityFetch;
@ -54,7 +54,7 @@ public interface ExpandingFetchSource extends FetchSource {
FetchStrategy fetchStrategy, FetchStrategy fetchStrategy,
LoadPlanBuildingContext loadPlanBuildingContext); LoadPlanBuildingContext loadPlanBuildingContext);
public BidirectionalEntityFetch buildBidirectionalEntityFetch( public BidirectionalEntityReference buildBidirectionalEntityReference(
AssociationAttributeDefinition attributeDefinition, AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy, FetchStrategy fetchStrategy,
EntityReference targetEntityReference, EntityReference targetEntityReference,

View File

@ -24,7 +24,6 @@
package org.hibernate.loader.plan2.build.spi; package org.hibernate.loader.plan2.build.spi;
import org.hibernate.loader.plan2.spi.CollectionQuerySpace; import org.hibernate.loader.plan2.spi.CollectionQuerySpace;
import org.hibernate.loader.plan2.spi.EntityQuerySpace;
import org.hibernate.loader.plan2.spi.QuerySpaces; import org.hibernate.loader.plan2.spi.QuerySpaces;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
@ -35,7 +34,7 @@ import org.hibernate.persister.entity.EntityPersister;
public interface ExpandingQuerySpaces extends QuerySpaces { public interface ExpandingQuerySpaces extends QuerySpaces {
public String generateImplicitUid(); public String generateImplicitUid();
public EntityQuerySpace makeEntityQuerySpace(String uid, EntityPersister entityPersister); public ExpandingEntityQuerySpace makeEntityQuerySpace(String uid, EntityPersister entityPersister);
public CollectionQuerySpace makeCollectionQuerySpace(String uid, CollectionPersister collectionPersister); public CollectionQuerySpace makeCollectionQuerySpace(String uid, CollectionPersister collectionPersister);
} }

View File

@ -27,7 +27,7 @@ import java.io.ByteArrayOutputStream;
import java.io.PrintStream; import java.io.PrintStream;
import java.io.PrintWriter; 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.CollectionFetch;
import org.hibernate.loader.plan2.spi.CollectionFetchableElement; import org.hibernate.loader.plan2.spi.CollectionFetchableElement;
import org.hibernate.loader.plan2.spi.CollectionFetchableIndex; import org.hibernate.loader.plan2.spi.CollectionFetchableIndex;
@ -153,7 +153,7 @@ public class ReturnGraphTreePrinter {
} }
private void writeEntityReferenceFetches(EntityReference entityReference, int depth, PrintWriter printWriter) { private void writeEntityReferenceFetches(EntityReference entityReference, int depth, PrintWriter printWriter) {
if ( BidirectionalEntityFetch.class.isInstance( entityReference ) ) { if ( BidirectionalEntityReference.class.isInstance( entityReference ) ) {
return; return;
} }
if ( entityReference.getIdentifierDescription().hasFetches() ) { if ( entityReference.getIdentifierDescription().hasFetches() ) {

View File

@ -39,7 +39,7 @@ import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.loader.plan2.exec.process.internal.HydratedEntityRegistration; import org.hibernate.loader.plan2.exec.process.internal.HydratedEntityRegistration;
import org.hibernate.loader.plan2.exec.process.internal.ResultSetProcessingContextImpl; 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.CompositeFetch;
import org.hibernate.loader.plan2.spi.EntityFetch; import org.hibernate.loader.plan2.spi.EntityFetch;
import org.hibernate.loader.plan2.spi.EntityIdentifierDescription; import org.hibernate.loader.plan2.spi.EntityIdentifierDescription;
@ -129,7 +129,7 @@ public abstract class AbstractRowReader implements RowReader {
final EntityReference entityReference = entityReferenceInitializer.getEntityReference(); final EntityReference entityReference = entityReferenceInitializer.getEntityReference();
final EntityIdentifierDescription identifierDescription = entityReference.getIdentifierDescription(); final EntityIdentifierDescription identifierDescription = entityReference.getIdentifierDescription();
if ( identifierDescription.hasFetches() ) { if ( identifierDescription.hasFetches() || identifierDescription.hasBidirectionalEntityReferences() ) {
resolveEntityKey( resultSet, context, (FetchSource) identifierDescription, initializerByEntityReference ); resolveEntityKey( resultSet, context, (FetchSource) identifierDescription, initializerByEntityReference );
} }
entityReferenceInitializer.resolveEntityKey( resultSet, context ); entityReferenceInitializer.resolveEntityKey( resultSet, context );
@ -140,27 +140,31 @@ public abstract class AbstractRowReader implements RowReader {
ResultSetProcessingContextImpl context, ResultSetProcessingContextImpl context,
FetchSource fetchSource, FetchSource fetchSource,
Map<EntityReference,EntityReferenceInitializer> initializerByEntityReference) throws SQLException { Map<EntityReference,EntityReferenceInitializer> 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() ) { for ( Fetch fetch : fetchSource.getFetches() ) {
if ( EntityFetch.class.isInstance( fetch ) ) { if ( EntityFetch.class.isInstance( fetch ) ) {
final EntityFetch entityFetch = (EntityFetch) fetch; final EntityFetch entityFetch = (EntityFetch) fetch;
final EntityReferenceInitializer targetEntityReferenceInitializer; final EntityReferenceInitializer entityReferenceInitializer = initializerByEntityReference.get( entityFetch );
if ( BidirectionalEntityFetch.class.isInstance( fetch ) ) { if ( entityReferenceInitializer != null ) {
final BidirectionalEntityFetch bidirectionalEntityFetch = (BidirectionalEntityFetch) fetch;
targetEntityReferenceInitializer = initializerByEntityReference.get(
bidirectionalEntityFetch.getTargetEntityReference()
);
}
else {
targetEntityReferenceInitializer = initializerByEntityReference.get( entityFetch );
}
if ( targetEntityReferenceInitializer != null ) {
resolveEntityKey( resolveEntityKey(
resultSet, resultSet,
context, context,
targetEntityReferenceInitializer, entityReferenceInitializer,
initializerByEntityReference initializerByEntityReference
); );
targetEntityReferenceInitializer.hydrateEntityState( resultSet, context ); entityReferenceInitializer.hydrateEntityState( resultSet, context );
} }
} }
else if ( CompositeFetch.class.isInstance( fetch ) ) { else if ( CompositeFetch.class.isInstance( fetch ) ) {

View File

@ -38,7 +38,7 @@ package org.hibernate.loader.plan2.spi;
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface BidirectionalEntityFetch { public interface BidirectionalEntityReference extends EntityReference {
/** /**
* Get the targeted EntityReference * Get the targeted EntityReference
* *

View File

@ -37,4 +37,13 @@ public interface EntityIdentifierDescription {
* non-empty results for {@link FetchSource#getFetches()} * non-empty results for {@link FetchSource#getFetches()}
*/ */
public boolean hasFetches(); 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();
} }

View File

@ -32,10 +32,6 @@ import org.hibernate.loader.PropertyPath;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface FetchSource { 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 * Get the property path to this fetch owner
@ -47,12 +43,19 @@ public interface FetchSource {
public String getQuerySpaceUid(); public String getQuerySpaceUid();
/** /**
* Retrieve the fetches owned by this return. * Retrieve the fetches owned by this fetch source.
* *
* @return The owned fetches. * @return The owned fetches.
*/ */
public Fetch[] getFetches(); 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. * Resolve the "current" {@link EntityReference}, or null if none.
* *

View File

@ -3792,8 +3792,6 @@ public abstract class AbstractEntityPersister
} }
private void doLateInit() { private void doLateInit() {
generateEntityDefinition();
//insert/update/delete SQL //insert/update/delete SQL
final int joinSpan = getTableSpan(); final int joinSpan = getTableSpan();
sqlDeleteStrings = new String[joinSpan]; sqlDeleteStrings = new String[joinSpan];
@ -3854,7 +3852,6 @@ public abstract class AbstractEntityPersister
public final void postInstantiate() throws MappingException { public final void postInstantiate() throws MappingException {
doLateInit(); doLateInit();
// generateEntityDefinition();
createLoaders(); createLoaders();
createUniqueKeyLoaders(); createUniqueKeyLoaders();
@ -5120,7 +5117,8 @@ public abstract class AbstractEntityPersister
private Iterable<AttributeDefinition> embeddedCompositeIdentifierAttributes; private Iterable<AttributeDefinition> embeddedCompositeIdentifierAttributes;
private Iterable<AttributeDefinition> attributeDefinitions; private Iterable<AttributeDefinition> attributeDefinitions;
protected void generateEntityDefinition() { @Override
public void generateEntityDefinition() {
prepareEntityIdentifierDefinition(); prepareEntityIdentifierDefinition();
collectAttributeDefinitions(); collectAttributeDefinitions();
} }

View File

@ -45,7 +45,6 @@ import org.hibernate.id.IdentifierGenerator;
import org.hibernate.internal.FilterAliasGenerator; import org.hibernate.internal.FilterAliasGenerator;
import org.hibernate.metadata.ClassMetadata; import org.hibernate.metadata.ClassMetadata;
import org.hibernate.persister.walking.spi.EntityDefinition; 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.EntityMetamodel;
import org.hibernate.tuple.entity.EntityTuplizer; import org.hibernate.tuple.entity.EntityTuplizer;
import org.hibernate.type.Type; import org.hibernate.type.Type;
@ -71,7 +70,14 @@ public interface EntityPersister extends OptimisticCacheSource, EntityDefinition
public static final String ENTITY_ID = "id"; 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.
* <p/> * <p/>
* Called only once per {@link org.hibernate.SessionFactory} lifecycle, * Called only once per {@link org.hibernate.SessionFactory} lifecycle,
* after all entity persisters have been instantiated. * after all entity persisters have been instantiated.

View File

@ -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();
}
}

View File

@ -35,7 +35,6 @@ import org.hibernate.persister.walking.spi.AssociationKey;
import org.hibernate.persister.walking.spi.AttributeDefinition; import org.hibernate.persister.walking.spi.AttributeDefinition;
import org.hibernate.persister.walking.spi.AttributeSource; import org.hibernate.persister.walking.spi.AttributeSource;
import org.hibernate.persister.walking.spi.CompositionDefinition; import org.hibernate.persister.walking.spi.CompositionDefinition;
import org.hibernate.persister.walking.spi.EntityDefinition;
import org.hibernate.tuple.AbstractNonIdentifierAttribute; import org.hibernate.tuple.AbstractNonIdentifierAttribute;
import org.hibernate.tuple.BaselineAttributeInformation; import org.hibernate.tuple.BaselineAttributeInformation;
import org.hibernate.type.AssociationType; import org.hibernate.type.AssociationType;
@ -54,14 +53,18 @@ import static org.hibernate.engine.internal.JoinHelper.getRHSColumnNames;
*/ */
public abstract class AbstractCompositionAttribute extends AbstractNonIdentifierAttribute implements public abstract class AbstractCompositionAttribute extends AbstractNonIdentifierAttribute implements
CompositionDefinition { CompositionDefinition {
private final int columnStartPosition;
protected AbstractCompositionAttribute( protected AbstractCompositionAttribute(
AttributeSource source, AttributeSource source,
SessionFactoryImplementor sessionFactory, SessionFactoryImplementor sessionFactory,
int attributeNumber, int entityBasedAttributeNumber,
String attributeName, String attributeName,
CompositeType attributeType, CompositeType attributeType,
int columnStartPosition,
BaselineAttributeInformation baselineInfo) { BaselineAttributeInformation baselineInfo) {
super( source, sessionFactory, attributeNumber, attributeName, attributeType, baselineInfo ); super( source, sessionFactory, entityBasedAttributeNumber, attributeName, attributeType, baselineInfo );
this.columnStartPosition = columnStartPosition;
} }
@Override @Override
@ -77,7 +80,7 @@ public abstract class AbstractCompositionAttribute extends AbstractNonIdentifier
return new Iterator<AttributeDefinition>() { return new Iterator<AttributeDefinition>() {
private final int numberOfAttributes = getType().getSubtypes().length; private final int numberOfAttributes = getType().getSubtypes().length;
private int currentSubAttributeNumber = 0; private int currentSubAttributeNumber = 0;
private int currentColumnPosition = 0; private int currentColumnPosition = columnStartPosition;
@Override @Override
public boolean hasNext() { public boolean hasNext() {
@ -106,13 +109,13 @@ public abstract class AbstractCompositionAttribute extends AbstractNonIdentifier
JoinHelper.getLHSTableName( JoinHelper.getLHSTableName(
aType, aType,
attributeNumber(), attributeNumber(),
(OuterJoinLoadable) getSource() (OuterJoinLoadable) locateOwningPersister()
), ),
JoinHelper.getLHSColumnNames( JoinHelper.getLHSColumnNames(
aType, aType,
attributeNumber(), attributeNumber(),
0, columnPosition,
(OuterJoinLoadable) getSource(), (OuterJoinLoadable) locateOwningPersister(),
sessionFactory() sessionFactory()
) )
); );
@ -129,24 +132,15 @@ public abstract class AbstractCompositionAttribute extends AbstractNonIdentifier
else { else {
final OuterJoinLoadable entityPersister = (OuterJoinLoadable) locateOwningPersister(); final OuterJoinLoadable entityPersister = (OuterJoinLoadable) locateOwningPersister();
lhsTableName = getLHSTableName( aType, attributeNumber(), entityPersister ); 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( lhsTableName, lhsColumnNames );
// associationKey = new AssociationKey(
// getLHSTableName(
// aType,
// attributeNumber(),
// (OuterJoinLoadable) locateOwningPersister()
// ),
// getLHSColumnNames(
// aType,
// attributeNumber(),
// columnPosition,
// (OuterJoinLoadable) locateOwningPersister(),
// sessionFactory()
// )
// );
} }
else { else {
associationKey = new AssociationKey( associationKey = new AssociationKey(
@ -156,12 +150,14 @@ public abstract class AbstractCompositionAttribute extends AbstractNonIdentifier
} }
final CompositeType cType = getType(); 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( return new CompositeBasedAssociationAttribute(
AbstractCompositionAttribute.this, AbstractCompositionAttribute.this,
sessionFactory(), sessionFactory(),
subAttributeNumber, attributeNumber(),
name, name,
(AssociationType) type, (AssociationType) type,
new BaselineAttributeInformation.Builder() new BaselineAttributeInformation.Builder()
@ -175,7 +171,7 @@ public abstract class AbstractCompositionAttribute extends AbstractNonIdentifier
.setCascadeStyle( getType().getCascadeStyle( subAttributeNumber ) ) .setCascadeStyle( getType().getCascadeStyle( subAttributeNumber ) )
.setFetchMode( getType().getFetchMode( subAttributeNumber ) ) .setFetchMode( getType().getFetchMode( subAttributeNumber ) )
.createInformation(), .createInformation(),
AbstractCompositionAttribute.this.attributeNumber(), subAttributeNumber,
associationKey associationKey
); );
} }
@ -183,9 +179,10 @@ public abstract class AbstractCompositionAttribute extends AbstractNonIdentifier
return new CompositionBasedCompositionAttribute( return new CompositionBasedCompositionAttribute(
AbstractCompositionAttribute.this, AbstractCompositionAttribute.this,
sessionFactory(), sessionFactory(),
subAttributeNumber, attributeNumber(),
name, name,
(CompositeType) type, (CompositeType) type,
columnPosition,
new BaselineAttributeInformation.Builder() new BaselineAttributeInformation.Builder()
.setInsertable( AbstractCompositionAttribute.this.isInsertable() ) .setInsertable( AbstractCompositionAttribute.this.isInsertable() )
.setUpdateable( AbstractCompositionAttribute.this.isUpdateable() ) .setUpdateable( AbstractCompositionAttribute.this.isUpdateable() )
@ -233,14 +230,7 @@ public abstract class AbstractCompositionAttribute extends AbstractNonIdentifier
}; };
} }
public EntityPersister locateOwningPersister() { protected abstract EntityPersister locateOwningPersister();
if ( EntityDefinition.class.isInstance( getSource() ) ) {
return ( (EntityDefinition) getSource() ).getEntityPersister();
}
else {
return ( (AbstractCompositionAttribute) getSource() ).locateOwningPersister();
}
}
@Override @Override
protected String loggableMetadata() { protected String loggableMetadata() {

View File

@ -43,31 +43,30 @@ import org.hibernate.persister.walking.spi.AssociationKey;
import org.hibernate.persister.walking.spi.CollectionDefinition; import org.hibernate.persister.walking.spi.CollectionDefinition;
import org.hibernate.persister.walking.spi.EntityDefinition; import org.hibernate.persister.walking.spi.EntityDefinition;
import org.hibernate.persister.walking.spi.WalkingException; import org.hibernate.persister.walking.spi.WalkingException;
import org.hibernate.tuple.AbstractNonIdentifierAttribute;
import org.hibernate.tuple.BaselineAttributeInformation; import org.hibernate.tuple.BaselineAttributeInformation;
import org.hibernate.tuple.NonIdentifierAttribute;
import org.hibernate.type.AnyType; import org.hibernate.type.AnyType;
import org.hibernate.type.AssociationType; import org.hibernate.type.AssociationType;
import org.hibernate.type.CompositeType;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class CompositeBasedAssociationAttribute public class CompositeBasedAssociationAttribute
extends AbstractCompositeBasedAttribute extends AbstractNonIdentifierAttribute
implements AssociationAttributeDefinition { implements NonIdentifierAttribute, AssociationAttributeDefinition {
private final int subAttributeNumber;
private final AssociationKey associationKey; private final AssociationKey associationKey;
private Joinable joinable; private Joinable joinable;
public CompositeBasedAssociationAttribute( public CompositeBasedAssociationAttribute(
AbstractCompositionAttribute source, AbstractCompositionAttribute source,
SessionFactoryImplementor factory, SessionFactoryImplementor factory,
int attributeNumber, int entityBasedAttributeNumber, String attributeName, AssociationType attributeType, BaselineAttributeInformation baselineInfo, int subAttributeNumber,
String attributeName,
AssociationType attributeType,
BaselineAttributeInformation baselineInfo,
int ownerAttributeNumber,
AssociationKey associationKey) { AssociationKey associationKey) {
super( source, factory, attributeNumber, attributeName, attributeType, baselineInfo, ownerAttributeNumber ); super( source, factory, entityBasedAttributeNumber, attributeName, attributeType, baselineInfo );
this.subAttributeNumber = subAttributeNumber;
this.associationKey = associationKey; this.associationKey = associationKey;
} }
@ -76,6 +75,11 @@ public class CompositeBasedAssociationAttribute
return (AssociationType) super.getType(); return (AssociationType) super.getType();
} }
@Override
public AbstractCompositionAttribute getSource() {
return (AbstractCompositionAttribute) super.getSource();
}
protected Joinable getJoinable() { protected Joinable getJoinable() {
if ( joinable == null ) { if ( joinable == null ) {
joinable = getType().getAssociatedJoinable( sessionFactory() ); joinable = getType().getAssociatedJoinable( sessionFactory() );
@ -148,37 +152,21 @@ public class CompositeBasedAssociationAttribute
@Override @Override
public FetchStrategy determineFetchPlan(LoadQueryInfluencers loadQueryInfluencers, PropertyPath propertyPath) { public FetchStrategy determineFetchPlan(LoadQueryInfluencers loadQueryInfluencers, PropertyPath propertyPath) {
final EntityPersister owningPersister = locateOwningPersister(); final EntityPersister owningPersister = getSource().locateOwningPersister();
FetchStyle style = determineFetchStyleByProfile( FetchStyle style = FetchStrategyHelper.determineFetchStyleByProfile(
loadQueryInfluencers, loadQueryInfluencers,
owningPersister, owningPersister,
propertyPath, propertyPath,
ownerAttributeNumber() attributeNumber()
); );
if ( style == null ) { if ( style == null ) {
style = determineFetchStyleByMetadata( style = determineFetchStyleByMetadata( getFetchMode(), getType() );
getSource().getType().getFetchMode( attributeNumber() ),
getType()
);
} }
return new FetchStrategy( determineFetchTiming( style ), style ); 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) { protected FetchStyle determineFetchStyleByMetadata(FetchMode fetchMode, AssociationType type) {
return FetchStrategyHelper.determineFetchStyleByMetadata( fetchMode, type, sessionFactory() ); return FetchStrategyHelper.determineFetchStyleByMetadata( fetchMode, type, sessionFactory() );
} }
@ -187,14 +175,9 @@ public class CompositeBasedAssociationAttribute
return FetchStrategyHelper.determineFetchTiming( style, getType(), sessionFactory() ); return FetchStrategyHelper.determineFetchTiming( style, getType(), sessionFactory() );
} }
private EntityPersister locateOwningPersister() {
return getSource().locateOwningPersister();
}
@Override @Override
public CascadeStyle determineCascadeStyle() { public CascadeStyle determineCascadeStyle() {
final CompositeType compositeType = (CompositeType) locateOwningPersister().getPropertyType( getName() ); return getCascadeStyle();
return compositeType.getCascadeStyle( attributeNumber() );
} }
private HydratedCompoundValueHandler hydratedCompoundValueHandler; private HydratedCompoundValueHandler hydratedCompoundValueHandler;
@ -205,12 +188,12 @@ public class CompositeBasedAssociationAttribute
hydratedCompoundValueHandler = new HydratedCompoundValueHandler() { hydratedCompoundValueHandler = new HydratedCompoundValueHandler() {
@Override @Override
public Object extract(Object hydratedState) { public Object extract(Object hydratedState) {
return ( (Object[] ) hydratedState )[ attributeNumber() ]; return ( (Object[] ) hydratedState )[ subAttributeNumber ];
} }
@Override @Override
public void inject(Object hydratedState, Object value) { public void inject(Object hydratedState, Object value) {
( (Object[] ) hydratedState )[ attributeNumber() ] = value; ( (Object[] ) hydratedState )[ subAttributeNumber ] = value;
} }
}; };
} }

View File

@ -24,22 +24,43 @@
package org.hibernate.tuple.component; package org.hibernate.tuple.component;
import org.hibernate.engine.spi.SessionFactoryImplementor; 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.tuple.BaselineAttributeInformation;
import org.hibernate.type.CompositeType; import org.hibernate.type.CompositeType;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class CompositionBasedCompositionAttribute public class CompositionBasedCompositionAttribute extends AbstractCompositionAttribute {
extends AbstractCompositionAttribute {
public CompositionBasedCompositionAttribute( public CompositionBasedCompositionAttribute(
CompositionDefinition source, AbstractCompositionAttribute source,
SessionFactoryImplementor sessionFactory, SessionFactoryImplementor sessionFactory,
int attributeNumber, int entityBasedAttributeNumber,
String attributeName, String attributeName,
CompositeType attributeType, CompositeType attributeType,
int columnStartPosition,
BaselineAttributeInformation baselineInfo) { 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();
}
} }
} }

View File

@ -44,6 +44,11 @@ public class EntityBasedCompositionAttribute
String attributeName, String attributeName,
CompositeType attributeType, CompositeType attributeType,
BaselineAttributeInformation baselineInfo) { BaselineAttributeInformation baselineInfo) {
super( source, factory, attributeNumber, attributeName, attributeType, baselineInfo ); super( source, factory, attributeNumber, attributeName, attributeType, 0, baselineInfo );
}
@Override
protected EntityPersister locateOwningPersister() {
return (EntityPersister) getSource();
} }
} }

View File

@ -115,6 +115,10 @@ public class GoofyPersisterClassProvider implements PersisterClassResolver {
return new NonPojoInstrumentationMetadata( null ); return new NonPojoInstrumentationMetadata( null );
} }
@Override
public void generateEntityDefinition() {
}
@Override @Override
public void postInstantiate() throws MappingException { public void postInstantiate() throws MappingException {

View File

@ -77,6 +77,10 @@ public class CustomPersister implements EntityPersister {
return Custom.class; return Custom.class;
} }
@Override
public void generateEntityDefinition() {
}
public void postInstantiate() throws MappingException {} public void postInstantiate() throws MappingException {}
public String getEntityName() { public String getEntityName() {

View File

@ -26,7 +26,7 @@ package org.hibernate.test.loadplans.plans;
import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Configuration;
import org.hibernate.engine.spi.SessionFactoryImplementor; 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.Country;
import org.hibernate.test.annotations.collectionelement.Boy; import org.hibernate.test.annotations.collectionelement.Boy;
import org.hibernate.test.annotations.collectionelement.Matrix; import org.hibernate.test.annotations.collectionelement.Matrix;
@ -226,18 +226,19 @@ public class LoadPlanStructureAssertionTest extends BaseUnitTestCase {
FetchSource.class, FetchSource.class,
cardFieldElementGraph.getIdentifierDescription() cardFieldElementGraph.getIdentifierDescription()
); );
assertEquals( 2, cardFieldElementGraphIdAsFetchSource.getFetches().length ); assertEquals( 1, cardFieldElementGraphIdAsFetchSource.getFetches().length );
assertEquals( 1, cardFieldElementGraphIdAsFetchSource.getBidirectionalEntityReferences().length );
BidirectionalEntityFetch circularCardFetch = assertTyping( BidirectionalEntityReference circularCardFetch = assertTyping(
BidirectionalEntityFetch.class, BidirectionalEntityReference.class,
cardFieldElementGraphIdAsFetchSource.getFetches()[0] cardFieldElementGraphIdAsFetchSource.getBidirectionalEntityReferences()[0]
); );
assertSame( circularCardFetch.getTargetEntityReference(), cardReturn ); assertSame( circularCardFetch.getTargetEntityReference(), cardReturn );
// the fetch above is to the other key-many-to-one for CardField.primaryKey composite: key // the fetch above is to the other key-many-to-one for CardField.primaryKey composite: key
EntityFetch keyFetch = assertTyping( EntityFetch keyFetch = assertTyping(
EntityFetch.class, EntityFetch.class,
cardFieldElementGraphIdAsFetchSource.getFetches()[1] cardFieldElementGraphIdAsFetchSource.getFetches()[0]
); );
assertEquals( Key.class.getName(), keyFetch.getEntityPersister().getEntityName() ); assertEquals( Key.class.getName(), keyFetch.getEntityPersister().getEntityName() );
} }

View File

@ -143,6 +143,10 @@ public class PersisterClassProviderTest {
return new NonPojoInstrumentationMetadata( getEntityName() ); return new NonPojoInstrumentationMetadata( getEntityName() );
} }
@Override
public void generateEntityDefinition() {
}
@Override @Override
public void postInstantiate() throws MappingException { public void postInstantiate() throws MappingException {