HHH-7841 - Redesign Loader

HHH-7841 - Redesign Loader

HHH-7841 - Redesign Loader

HHH-7841 - Redesign Loader
This commit is contained in:
Gail Badner 2013-05-16 20:30:00 -07:00
parent 7bd9ba2adf
commit 043d618c03
37 changed files with 947 additions and 608 deletions

View File

@ -56,12 +56,11 @@ public abstract class AbstractJoinableAssociationImpl implements JoinableAssocia
EntityReference currentEntityReference, EntityReference currentEntityReference,
CollectionReference currentCollectionReference, CollectionReference currentCollectionReference,
String withClause, String withClause,
boolean isNullable,
boolean hasRestriction, boolean hasRestriction,
Map<String, Filter> enabledFilters) throws MappingException { Map<String, Filter> enabledFilters) throws MappingException {
this.propertyPath = currentFetch.getPropertyPath(); this.propertyPath = currentFetch.getPropertyPath();
if ( currentFetch.getFetchStrategy().getStyle() == FetchStyle.JOIN ) { if ( currentFetch.getFetchStrategy().getStyle() == FetchStyle.JOIN ) {
joinType = isNullable ? JoinType.LEFT_OUTER_JOIN : JoinType.INNER_JOIN; joinType = currentFetch.isNullable() ? JoinType.LEFT_OUTER_JOIN : JoinType.INNER_JOIN;
} }
else { else {
joinType = JoinType.NONE; joinType = JoinType.NONE;

View File

@ -56,7 +56,6 @@ public class CollectionJoinableAssociationImpl extends AbstractJoinableAssociati
currentEntityReference, currentEntityReference,
collectionFetch, collectionFetch,
withClause, withClause,
true,
hasRestriction, hasRestriction,
enabledFilters enabledFilters
); );

View File

@ -48,7 +48,6 @@ public class EntityJoinableAssociationImpl extends AbstractJoinableAssociationIm
EntityFetch entityFetch, EntityFetch entityFetch,
CollectionReference currentCollectionReference, CollectionReference currentCollectionReference,
String withClause, String withClause,
boolean isNullable,
boolean hasRestriction, boolean hasRestriction,
Map<String, Filter> enabledFilters) throws MappingException { Map<String, Filter> enabledFilters) throws MappingException {
super( super(
@ -56,7 +55,6 @@ public class EntityJoinableAssociationImpl extends AbstractJoinableAssociationIm
entityFetch, entityFetch,
currentCollectionReference, currentCollectionReference,
withClause, withClause,
isNullable,
hasRestriction, hasRestriction,
enabledFilters enabledFilters
); );

View File

@ -149,14 +149,10 @@ public class EntityLoadQueryBuilderImpl implements LoadQueryBuilder {
@Override @Override
public void startingEntityFetch(EntityFetch entityFetch) { public void startingEntityFetch(EntityFetch entityFetch) {
final OuterJoinLoadable ownerPersister = (OuterJoinLoadable) entityFetch.getOwner().retrieveFetchSourcePersister();
final int propertyNumber = ownerPersister.getEntityMetamodel().getPropertyIndex( entityFetch.getOwnerPropertyName() );
final boolean isNullable = ownerPersister.isSubclassPropertyNullable( propertyNumber );
EntityJoinableAssociationImpl assoc = new EntityJoinableAssociationImpl( EntityJoinableAssociationImpl assoc = new EntityJoinableAssociationImpl(
entityFetch, entityFetch,
getCurrentCollectionReference(), getCurrentCollectionReference(),
"", // getWithClause( entityFetch.getPropertyPath() ) "", // getWithClause( entityFetch.getPropertyPath() )
isNullable,
false, // hasRestriction( entityFetch.getPropertyPath() ) false, // hasRestriction( entityFetch.getPropertyPath() )
loadQueryInfluencers.getEnabledFilters() loadQueryInfluencers.getEnabledFilters()
); );

View File

@ -27,7 +27,6 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.hibernate.cfg.NotYetImplementedException; import org.hibernate.cfg.NotYetImplementedException;
import org.hibernate.engine.internal.JoinHelper;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.loader.CollectionAliases; import org.hibernate.loader.CollectionAliases;
@ -36,6 +35,8 @@ import org.hibernate.loader.EntityAliases;
import org.hibernate.loader.GeneratedCollectionAliases; import org.hibernate.loader.GeneratedCollectionAliases;
import org.hibernate.loader.plan.spi.CollectionReference; import org.hibernate.loader.plan.spi.CollectionReference;
import org.hibernate.loader.plan.spi.CollectionReturn; import org.hibernate.loader.plan.spi.CollectionReturn;
import org.hibernate.loader.plan.spi.CompositeElementGraph;
import org.hibernate.loader.plan.spi.CompositeIndexGraph;
import org.hibernate.loader.plan.spi.EntityReference; import org.hibernate.loader.plan.spi.EntityReference;
import org.hibernate.loader.plan.spi.EntityReturn; import org.hibernate.loader.plan.spi.EntityReturn;
import org.hibernate.loader.plan.spi.Fetch; import org.hibernate.loader.plan.spi.Fetch;
@ -46,7 +47,6 @@ import org.hibernate.loader.spi.LoadQueryAliasResolutionContext;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Loadable; import org.hibernate.persister.entity.Loadable;
import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.type.EntityType; import org.hibernate.type.EntityType;
/** /**
@ -214,9 +214,18 @@ public class LoadQueryAliasResolutionContextImpl implements LoadQueryAliasResolu
if ( EntityReference.class.isInstance( currentFetch.getOwner() ) ) { if ( EntityReference.class.isInstance( currentFetch.getOwner() ) ) {
lhsAlias = resolveEntityTableAlias( (EntityReference) currentFetch.getOwner() ); lhsAlias = resolveEntityTableAlias( (EntityReference) currentFetch.getOwner() );
} }
else { else if ( CompositeElementGraph.class.isInstance( currentFetch.getOwner() ) ) {
throw new NotYetImplementedException( "Cannot determine LHS alias for a FetchOwner that is not an EntityReference yet." ); CompositeElementGraph compositeElementGraph = (CompositeElementGraph) currentFetch.getOwner();
lhsAlias = resolveCollectionTableAlias( compositeElementGraph.getCollectionReference() );
} }
else if ( CompositeIndexGraph.class.isInstance( currentFetch.getOwner() ) ) {
CompositeIndexGraph compositeIndexGraph = (CompositeIndexGraph) currentFetch.getOwner();
lhsAlias = resolveCollectionTableAlias( compositeIndexGraph.getCollectionReference() );
}
else {
throw new NotYetImplementedException( "Cannot determine LHS alias for FetchOwner." );
}
final String[] aliasedLhsColumnNames = StringHelper.qualify( lhsAlias, currentFetch.getColumnNames() );
final String rhsAlias; final String rhsAlias;
if ( EntityReference.class.isInstance( currentFetch ) ) { if ( EntityReference.class.isInstance( currentFetch ) ) {
rhsAlias = resolveEntityTableAlias( (EntityReference) currentFetch ); rhsAlias = resolveEntityTableAlias( (EntityReference) currentFetch );
@ -229,15 +238,6 @@ public class LoadQueryAliasResolutionContextImpl implements LoadQueryAliasResolu
} }
// TODO: can't this be found in CollectionAliases or EntityAliases? should be moved to LoadQueryAliasResolutionContextImpl // TODO: can't this be found in CollectionAliases or EntityAliases? should be moved to LoadQueryAliasResolutionContextImpl
final OuterJoinLoadable fetchSourcePersister = (OuterJoinLoadable) currentFetch.getOwner().retrieveFetchSourcePersister();
final int propertyNumber = fetchSourcePersister.getEntityMetamodel().getPropertyIndex( currentFetch.getOwnerPropertyName() );
final String[] aliasedLhsColumnNames = JoinHelper.getAliasedLHSColumnNames(
joinableAssociation.getAssociationType(),
lhsAlias,
propertyNumber,
fetchSourcePersister,
sessionFactory
);
aliases = new JoinableAssociationAliasesImpl( lhsAlias, aliasedLhsColumnNames, rhsAlias ); aliases = new JoinableAssociationAliasesImpl( lhsAlias, aliasedLhsColumnNames, rhsAlias );
aliasesByJoinableAssociation.put( joinableAssociation, aliases ); aliasesByJoinableAssociation.put( joinableAssociation, aliases );

View File

@ -27,20 +27,24 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import org.hibernate.LockMode; import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
import org.hibernate.persister.walking.spi.CompositionDefinition;
import org.hibernate.type.Type;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
* @author Gail Badner
*/ */
public abstract class AbstractFetchOwner extends AbstractPlanNode implements FetchOwner { public abstract class AbstractFetchOwner extends AbstractPlanNode implements FetchOwner {
private final LockMode lockMode;
private List<Fetch> fetches; private List<Fetch> fetches;
public AbstractFetchOwner(SessionFactoryImplementor factory, LockMode lockMode) { public AbstractFetchOwner(SessionFactoryImplementor factory) {
super( factory ); super( factory );
this.lockMode = lockMode;
validate(); validate();
} }
@ -50,11 +54,10 @@ public abstract class AbstractFetchOwner extends AbstractPlanNode implements Fet
/** /**
* A "copy" constructor. Used while making clones/copies of this. * A "copy" constructor. Used while making clones/copies of this.
* *
* @param original * @param original - the original object to copy.
*/ */
protected AbstractFetchOwner(AbstractFetchOwner original, CopyContext copyContext) { protected AbstractFetchOwner(AbstractFetchOwner original, CopyContext copyContext) {
super( original ); super( original );
this.lockMode = original.lockMode;
validate(); validate();
copyContext.getReturnGraphVisitationStrategy().startingFetches( original ); copyContext.getReturnGraphVisitationStrategy().startingFetches( original );
@ -62,6 +65,7 @@ public abstract class AbstractFetchOwner extends AbstractPlanNode implements Fet
this.fetches = Collections.emptyList(); this.fetches = Collections.emptyList();
} }
else { else {
// TODO: don't think this is correct...
List<Fetch> fetchesCopy = new ArrayList<Fetch>(); List<Fetch> fetchesCopy = new ArrayList<Fetch>();
for ( Fetch fetch : fetches ) { for ( Fetch fetch : fetches ) {
fetchesCopy.add( fetch.makeCopy( copyContext, this ) ); fetchesCopy.add( fetch.makeCopy( copyContext, this ) );
@ -71,11 +75,6 @@ public abstract class AbstractFetchOwner extends AbstractPlanNode implements Fet
copyContext.getReturnGraphVisitationStrategy().finishingFetches( original ); copyContext.getReturnGraphVisitationStrategy().finishingFetches( original );
} }
public LockMode getLockMode() {
return lockMode;
}
@Override
public void addFetch(Fetch fetch) { public void addFetch(Fetch fetch) {
if ( fetch.getOwner() != this ) { if ( fetch.getOwner() != this ) {
throw new IllegalArgumentException( "Fetch and owner did not match" ); throw new IllegalArgumentException( "Fetch and owner did not match" );
@ -92,4 +91,55 @@ public abstract class AbstractFetchOwner extends AbstractPlanNode implements Fet
public Fetch[] getFetches() { public Fetch[] getFetches() {
return fetches == null ? NO_FETCHES : fetches.toArray( new Fetch[ fetches.size() ] ); return fetches == null ? NO_FETCHES : fetches.toArray( new Fetch[ fetches.size() ] );
} }
protected abstract FetchOwnerDelegate getFetchOwnerDelegate();
@Override
public boolean isNullable(Fetch fetch) {
return getFetchOwnerDelegate().isNullable( fetch );
}
@Override
public Type getType(Fetch fetch) {
return getFetchOwnerDelegate().getType( fetch );
}
@Override
public String[] getColumnNames(Fetch fetch) {
return getFetchOwnerDelegate().getColumnNames( fetch );
}
@Override
public CollectionFetch buildCollectionFetch(
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy,
LoadPlanBuildingContext loadPlanBuildingContext) {
return LoadPlanBuildingHelper.buildStandardCollectionFetch(
this,
attributeDefinition,
fetchStrategy,
loadPlanBuildingContext
);
}
@Override
public EntityFetch buildEntityFetch(
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy,
LoadPlanBuildingContext loadPlanBuildingContext) {
return LoadPlanBuildingHelper.buildStandardEntityFetch(
this,
attributeDefinition,
fetchStrategy,
loadPlanBuildingContext
);
}
@Override
public CompositeFetch buildCompositeFetch(
CompositionDefinition attributeDefinition,
LoadPlanBuildingContext loadPlanBuildingContext) {
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
}
} }

View File

@ -24,7 +24,6 @@
package org.hibernate.loader.plan.spi; package org.hibernate.loader.plan.spi;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.engine.FetchStrategy; import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.FetchStyle; import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -42,11 +41,10 @@ public abstract class AbstractSingularAttributeFetch extends AbstractFetchOwner
public AbstractSingularAttributeFetch( public AbstractSingularAttributeFetch(
SessionFactoryImplementor factory, SessionFactoryImplementor factory,
LockMode lockMode,
FetchOwner owner, FetchOwner owner,
String ownerProperty, String ownerProperty,
FetchStrategy fetchStrategy) { FetchStrategy fetchStrategy) {
super( factory, lockMode ); super( factory );
this.owner = owner; this.owner = owner;
this.ownerProperty = ownerProperty; this.ownerProperty = ownerProperty;
this.fetchStrategy = fetchStrategy; this.fetchStrategy = fetchStrategy;
@ -77,6 +75,16 @@ public abstract class AbstractSingularAttributeFetch extends AbstractFetchOwner
return ownerProperty; return ownerProperty;
} }
@Override
public boolean isNullable() {
return owner.isNullable( this );
}
@Override
public String[] getColumnNames() {
return owner.getColumnNames( this );
}
@Override @Override
public FetchStrategy getFetchStrategy() { public FetchStrategy getFetchStrategy() {
return fetchStrategy; return fetchStrategy;

View File

@ -28,8 +28,10 @@ import java.sql.SQLException;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.engine.FetchStrategy; import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.internal.JoinHelper;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.spi.ResultSetProcessingContext; import org.hibernate.loader.spi.ResultSetProcessingContext;
import org.hibernate.persister.entity.Joinable;
import org.hibernate.type.CollectionType; import org.hibernate.type.CollectionType;
/** /**
@ -74,6 +76,16 @@ public class CollectionFetch extends AbstractCollectionReference implements Fetc
return getPropertyPath().getProperty(); return getPropertyPath().getProperty();
} }
@Override
public boolean isNullable() {
return true;
}
@Override
public String[] getColumnNames() {
return getOwner().getColumnNames( this );
}
@Override @Override
public FetchStrategy getFetchStrategy() { public FetchStrategy getFetchStrategy() {
return fetchStrategy; return fetchStrategy;

View File

@ -1,29 +1,24 @@
package org.hibernate.loader.plan.spi; package org.hibernate.loader.plan.spi;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.engine.FetchStrategy; import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.PropertyPath; import org.hibernate.loader.PropertyPath;
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext; import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.collection.QueryableCollection;
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.persister.walking.spi.CompositionDefinition; import org.hibernate.type.CompositeType;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class CompositeElementGraph extends AbstractPlanNode implements FetchableCollectionElement { public class CompositeElementGraph extends AbstractFetchOwner implements FetchableCollectionElement {
private final CollectionReference collectionReference; private final CollectionReference collectionReference;
private final PropertyPath propertyPath; private final PropertyPath propertyPath;
private final CollectionPersister collectionPersister; private final CollectionPersister collectionPersister;
private final FetchOwnerDelegate fetchOwnerDelegate;
private List<Fetch> fetches;
public CompositeElementGraph( public CompositeElementGraph(
SessionFactoryImplementor sessionFactory, SessionFactoryImplementor sessionFactory,
@ -34,39 +29,24 @@ public class CompositeElementGraph extends AbstractPlanNode implements Fetchable
this.collectionReference = collectionReference; this.collectionReference = collectionReference;
this.collectionPersister = collectionReference.getCollectionPersister(); this.collectionPersister = collectionReference.getCollectionPersister();
this.propertyPath = collectionPath.append( "<elements>" ); this.propertyPath = collectionPath.append( "<elements>" );
this.fetchOwnerDelegate = new CompositeFetchOwnerDelegate(
sessionFactory,
(CompositeType) collectionPersister.getElementType(),
( (QueryableCollection) collectionPersister ).getElementColumnNames()
);
} }
public CompositeElementGraph(CompositeElementGraph original, CopyContext copyContext) { public CompositeElementGraph(CompositeElementGraph original, CopyContext copyContext) {
super( original ); super( original, copyContext );
this.collectionReference = original.collectionReference; this.collectionReference = original.collectionReference;
this.collectionPersister = original.collectionPersister; this.collectionPersister = original.collectionPersister;
this.propertyPath = original.propertyPath; this.propertyPath = original.propertyPath;
this.fetchOwnerDelegate = original.fetchOwnerDelegate;
copyContext.getReturnGraphVisitationStrategy().startingFetches( original );
if ( fetches == null || fetches.size() == 0 ) {
this.fetches = Collections.emptyList();
}
else {
List<Fetch> fetchesCopy = new ArrayList<Fetch>();
for ( Fetch fetch : fetches ) {
fetchesCopy.add( fetch.makeCopy( copyContext, this ) );
}
this.fetches = fetchesCopy;
}
copyContext.getReturnGraphVisitationStrategy().finishingFetches( original );
} }
@Override @Override
public void addFetch(Fetch fetch) { public CollectionReference getCollectionReference() {
if ( fetches == null ) { return collectionReference;
fetches = new ArrayList<Fetch>();
}
fetches.add( fetch );
}
@Override
public Fetch[] getFetches() {
return fetches == null ? NO_FETCHES : fetches.toArray( new Fetch[ fetches.size() ] );
} }
@Override @Override
@ -83,6 +63,16 @@ public class CompositeElementGraph extends AbstractPlanNode implements Fetchable
return propertyPath; return propertyPath;
} }
@Override
public CompositeElementGraph makeCopy(CopyContext copyContext) {
return new CompositeElementGraph( this, copyContext );
}
@Override
protected FetchOwnerDelegate getFetchOwnerDelegate() {
return fetchOwnerDelegate;
}
@Override @Override
public CollectionFetch buildCollectionFetch( public CollectionFetch buildCollectionFetch(
AssociationAttributeDefinition attributeDefinition, AssociationAttributeDefinition attributeDefinition,
@ -90,29 +80,4 @@ public class CompositeElementGraph extends AbstractPlanNode implements Fetchable
LoadPlanBuildingContext loadPlanBuildingContext) { LoadPlanBuildingContext loadPlanBuildingContext) {
throw new HibernateException( "Collection composite element cannot define collections" ); throw new HibernateException( "Collection composite element cannot define collections" );
} }
@Override
public EntityFetch buildEntityFetch(
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy,
LoadPlanBuildingContext loadPlanBuildingContext) {
return LoadPlanBuildingHelper.buildStandardEntityFetch(
this,
attributeDefinition,
fetchStrategy,
loadPlanBuildingContext
);
}
@Override
public CompositeFetch buildCompositeFetch(
CompositionDefinition attributeDefinition,
LoadPlanBuildingContext loadPlanBuildingContext) {
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
}
@Override
public CompositeElementGraph makeCopy(CopyContext copyContext) {
return new CompositeElementGraph( this, copyContext );
}
} }

View File

@ -25,8 +25,6 @@ package org.hibernate.loader.plan.spi;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import org.hibernate.LockMode;
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;
@ -37,6 +35,7 @@ import org.hibernate.loader.spi.ResultSetProcessingContext;
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.persister.walking.spi.CompositionDefinition; import org.hibernate.persister.walking.spi.CompositionDefinition;
import org.hibernate.type.CompositeType;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
@ -44,15 +43,28 @@ import org.hibernate.persister.walking.spi.CompositionDefinition;
public class CompositeFetch extends AbstractSingularAttributeFetch { public class CompositeFetch extends AbstractSingularAttributeFetch {
public static final FetchStrategy FETCH_PLAN = new FetchStrategy( FetchTiming.IMMEDIATE, FetchStyle.JOIN ); public static final FetchStrategy FETCH_PLAN = new FetchStrategy( FetchTiming.IMMEDIATE, FetchStyle.JOIN );
private final FetchOwnerDelegate delegate;
public CompositeFetch( public CompositeFetch(
SessionFactoryImplementor sessionFactory, SessionFactoryImplementor sessionFactory,
FetchOwner owner, FetchOwner owner,
String ownerProperty) { String ownerProperty) {
super( sessionFactory, LockMode.NONE, owner, ownerProperty, FETCH_PLAN ); super( sessionFactory, owner, ownerProperty, FETCH_PLAN );
this.delegate = new CompositeFetchOwnerDelegate(
sessionFactory,
(CompositeType) getOwner().getType( this ),
getOwner().getColumnNames( this )
);
} }
public CompositeFetch(CompositeFetch original, CopyContext copyContext, FetchOwner fetchOwnerCopy) { public CompositeFetch(CompositeFetch original, CopyContext copyContext, FetchOwner fetchOwnerCopy) {
super( original, copyContext, fetchOwnerCopy ); super( original, copyContext, fetchOwnerCopy );
this.delegate = original.getFetchOwnerDelegate();
}
@Override
protected FetchOwnerDelegate getFetchOwnerDelegate() {
return delegate;
} }
@Override @Override

View File

@ -0,0 +1,98 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.loader.plan.spi;
import java.util.Arrays;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.persister.walking.spi.WalkingException;
import org.hibernate.type.CompositeType;
import org.hibernate.type.Type;
/**
* @author Gail Badner
*/
public class CompositeFetchOwnerDelegate implements FetchOwnerDelegate {
private final SessionFactoryImplementor sessionFactory;
private final CompositeType compositeType;
private final String[] columnNames;
public CompositeFetchOwnerDelegate(
SessionFactoryImplementor sessionFactory,
CompositeType compositeType,
String[] columnNames) {
this.sessionFactory = sessionFactory;
this.compositeType = compositeType;
this.columnNames = columnNames;
}
@Override
public boolean isNullable(Fetch fetch) {
return compositeType.getPropertyNullability()[ determinePropertyIndex( fetch ) ];
}
@Override
public Type getType(Fetch fetch) {
return compositeType.getSubtypes()[ determinePropertyIndex( fetch ) ];
}
@Override
public String[] getColumnNames(Fetch fetch) {
// TODO: probably want to cache this
int begin = 0;
String[] subColumnNames = null;
for ( int i = 0; i < compositeType.getSubtypes().length; i++ ) {
final int columnSpan = compositeType.getSubtypes()[i].getColumnSpan( sessionFactory );
subColumnNames = ArrayHelper.slice( columnNames, begin, columnSpan );
if ( compositeType.getPropertyNames()[ i ].equals( fetch.getOwnerPropertyName() ) ) {
break;
}
begin += columnSpan;
}
return subColumnNames;
}
private int determinePropertyIndex(Fetch fetch) {
// TODO: probably want to cache this
final String[] subAttributeNames = compositeType.getPropertyNames();
int subAttributeIndex = -1;
for ( int i = 0; i < subAttributeNames.length ; i++ ) {
if ( subAttributeNames[ i ].equals( fetch.getOwnerPropertyName() ) ) {
subAttributeIndex = i;
break;
}
}
if ( subAttributeIndex == -1 ) {
throw new WalkingException(
String.format(
"Owner property [%s] not found in composite properties [%s]",
fetch.getOwnerPropertyName(),
Arrays.asList( subAttributeNames )
)
);
}
return subAttributeIndex;
}
}

View File

@ -1,29 +1,24 @@
package org.hibernate.loader.plan.spi; package org.hibernate.loader.plan.spi;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.engine.FetchStrategy; import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.PropertyPath; import org.hibernate.loader.PropertyPath;
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext; import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.collection.QueryableCollection;
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.persister.walking.spi.CompositionDefinition; import org.hibernate.type.CompositeType;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class CompositeIndexGraph extends AbstractPlanNode implements FetchableCollectionIndex { public class CompositeIndexGraph extends AbstractFetchOwner implements FetchableCollectionIndex {
private final CollectionReference collectionReference; private final CollectionReference collectionReference;
private final PropertyPath propertyPath; private final PropertyPath propertyPath;
private final CollectionPersister collectionPersister; private final CollectionPersister collectionPersister;
private final FetchOwnerDelegate fetchOwnerDelegate;
private List<Fetch> fetches;
public CompositeIndexGraph( public CompositeIndexGraph(
SessionFactoryImplementor sessionFactory, SessionFactoryImplementor sessionFactory,
@ -33,39 +28,19 @@ public class CompositeIndexGraph extends AbstractPlanNode implements FetchableCo
this.collectionReference = collectionReference; this.collectionReference = collectionReference;
this.collectionPersister = collectionReference.getCollectionPersister(); this.collectionPersister = collectionReference.getCollectionPersister();
this.propertyPath = propertyPath.append( "<index>" ); this.propertyPath = propertyPath.append( "<index>" );
this.fetchOwnerDelegate = new CompositeFetchOwnerDelegate(
sessionFactory,
(CompositeType) collectionPersister.getIndexType(),
( (QueryableCollection) collectionPersister ).getIndexColumnNames()
);
} }
protected CompositeIndexGraph(CompositeIndexGraph original, CopyContext copyContext) { protected CompositeIndexGraph(CompositeIndexGraph original, CopyContext copyContext) {
super( original ); super( original, copyContext );
this.collectionReference = original.collectionReference; this.collectionReference = original.collectionReference;
this.collectionPersister = original.collectionPersister; this.collectionPersister = original.collectionPersister;
this.propertyPath = original.propertyPath; this.propertyPath = original.propertyPath;
this.fetchOwnerDelegate = original.fetchOwnerDelegate;
copyContext.getReturnGraphVisitationStrategy().startingFetches( original );
if ( fetches == null || fetches.size() == 0 ) {
this.fetches = Collections.emptyList();
}
else {
List<Fetch> fetchesCopy = new ArrayList<Fetch>();
for ( Fetch fetch : fetches ) {
fetchesCopy.add( fetch.makeCopy( copyContext, this ) );
}
this.fetches = fetchesCopy;
}
copyContext.getReturnGraphVisitationStrategy().finishingFetches( original );
}
@Override
public void addFetch(Fetch fetch) {
if ( fetches == null ) {
fetches = new ArrayList<Fetch>();
}
fetches.add( fetch );
}
@Override
public Fetch[] getFetches() {
return fetches == null ? NO_FETCHES : fetches.toArray( new Fetch[ fetches.size() ] );
} }
@Override @Override
@ -77,12 +52,25 @@ public class CompositeIndexGraph extends AbstractPlanNode implements FetchableCo
return collectionPersister.getOwnerEntityPersister(); return collectionPersister.getOwnerEntityPersister();
} }
public CollectionReference getCollectionReference() {
return collectionReference;
}
@Override @Override
public PropertyPath getPropertyPath() { public PropertyPath getPropertyPath() {
return propertyPath; return propertyPath;
} }
@Override @Override
public CompositeIndexGraph makeCopy(CopyContext copyContext) {
return new CompositeIndexGraph( this, copyContext );
}
@Override
protected FetchOwnerDelegate getFetchOwnerDelegate() {
return fetchOwnerDelegate;
}
public CollectionFetch buildCollectionFetch( public CollectionFetch buildCollectionFetch(
AssociationAttributeDefinition attributeDefinition, AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy, FetchStrategy fetchStrategy,
@ -90,28 +78,4 @@ public class CompositeIndexGraph extends AbstractPlanNode implements FetchableCo
throw new HibernateException( "Composite index cannot define collections" ); throw new HibernateException( "Composite index cannot define collections" );
} }
@Override
public EntityFetch buildEntityFetch(
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy,
LoadPlanBuildingContext loadPlanBuildingContext) {
return LoadPlanBuildingHelper.buildStandardEntityFetch(
this,
attributeDefinition,
fetchStrategy,
loadPlanBuildingContext
);
}
@Override
public CompositeFetch buildCompositeFetch(
CompositionDefinition attributeDefinition,
LoadPlanBuildingContext loadPlanBuildingContext) {
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
}
@Override
public CompositeIndexGraph makeCopy(CopyContext copyContext) {
return new CompositeIndexGraph( this, copyContext );
}
} }

View File

@ -1,32 +1,23 @@
package org.hibernate.loader.plan.spi; package org.hibernate.loader.plan.spi;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.engine.FetchStrategy; import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.PropertyPath; import org.hibernate.loader.PropertyPath;
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.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.type.AssociationType; import org.hibernate.type.AssociationType;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class EntityElementGraph extends AbstractPlanNode implements FetchableCollectionElement, EntityReference { public class EntityElementGraph extends AbstractFetchOwner implements FetchableCollectionElement, EntityReference {
private final CollectionReference collectionReference; private final CollectionReference collectionReference;
private final CollectionPersister collectionPersister; private final CollectionPersister collectionPersister;
private final AssociationType elementType; private final AssociationType elementType;
private final EntityPersister elementPersister; private final EntityPersister elementPersister;
private final PropertyPath propertyPath; private final PropertyPath propertyPath;
private final FetchOwnerDelegate fetchOwnerDelegate;
private List<Fetch> fetches;
private IdentifierDescription identifierDescription; private IdentifierDescription identifierDescription;
@ -40,30 +31,19 @@ public class EntityElementGraph extends AbstractPlanNode implements FetchableCol
this.collectionPersister = collectionReference.getCollectionPersister(); this.collectionPersister = collectionReference.getCollectionPersister();
this.elementType = (AssociationType) collectionPersister.getElementType(); this.elementType = (AssociationType) collectionPersister.getElementType();
this.elementPersister = (EntityPersister) this.elementType.getAssociatedJoinable( sessionFactory() ); this.elementPersister = (EntityPersister) this.elementType.getAssociatedJoinable( sessionFactory() );
this.propertyPath = collectionPath.append( "<elements>" ); this.propertyPath = collectionPath;
this.fetchOwnerDelegate = new EntityFetchOwnerDelegate( elementPersister );
} }
public EntityElementGraph(EntityElementGraph original, CopyContext copyContext) { public EntityElementGraph(EntityElementGraph original, CopyContext copyContext) {
super( original ); super( original, copyContext );
this.collectionReference = original.collectionReference; this.collectionReference = original.collectionReference;
this.collectionPersister = original.collectionReference.getCollectionPersister(); this.collectionPersister = original.collectionReference.getCollectionPersister();
this.elementType = original.elementType; this.elementType = original.elementType;
this.elementPersister = original.elementPersister; this.elementPersister = original.elementPersister;
this.propertyPath = original.propertyPath; this.propertyPath = original.propertyPath;
this.fetchOwnerDelegate = original.fetchOwnerDelegate;
copyContext.getReturnGraphVisitationStrategy().startingFetches( original );
if ( fetches == null || fetches.size() == 0 ) {
this.fetches = Collections.emptyList();
}
else {
List<Fetch> fetchesCopy = new ArrayList<Fetch>();
for ( Fetch fetch : fetches ) {
fetchesCopy.add( fetch.makeCopy( copyContext, this ) );
}
this.fetches = fetchesCopy;
}
copyContext.getReturnGraphVisitationStrategy().finishingFetches( original );
} }
@Override @Override
@ -86,19 +66,6 @@ public class EntityElementGraph extends AbstractPlanNode implements FetchableCol
return identifierDescription; return identifierDescription;
} }
@Override
public void addFetch(Fetch fetch) {
if ( fetches == null ) {
fetches = new ArrayList<Fetch>();
}
fetches.add( fetch );
}
@Override
public Fetch[] getFetches() {
return fetches == null ? NO_FETCHES : fetches.toArray( new Fetch[ fetches.size() ] );
}
@Override @Override
public void validateFetchPlan(FetchStrategy fetchStrategy) { public void validateFetchPlan(FetchStrategy fetchStrategy) {
} }
@ -113,39 +80,6 @@ public class EntityElementGraph extends AbstractPlanNode implements FetchableCol
return propertyPath; return propertyPath;
} }
@Override
public CollectionFetch buildCollectionFetch(
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy,
LoadPlanBuildingContext loadPlanBuildingContext) {
return LoadPlanBuildingHelper.buildStandardCollectionFetch(
this,
attributeDefinition,
fetchStrategy,
loadPlanBuildingContext
);
}
@Override
public EntityFetch buildEntityFetch(
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy,
LoadPlanBuildingContext loadPlanBuildingContext) {
return LoadPlanBuildingHelper.buildStandardEntityFetch(
this,
attributeDefinition,
fetchStrategy,
loadPlanBuildingContext
);
}
@Override
public CompositeFetch buildCompositeFetch(
CompositionDefinition attributeDefinition,
LoadPlanBuildingContext loadPlanBuildingContext) {
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
}
@Override @Override
public void injectIdentifierDescription(IdentifierDescription identifierDescription) { public void injectIdentifierDescription(IdentifierDescription identifierDescription) {
this.identifierDescription = identifierDescription; this.identifierDescription = identifierDescription;
@ -156,8 +90,18 @@ public class EntityElementGraph extends AbstractPlanNode implements FetchableCol
return new EntityElementGraph( this, copyContext ); return new EntityElementGraph( this, copyContext );
} }
@Override
public CollectionReference getCollectionReference() {
return collectionReference;
}
@Override @Override
public String toString() { public String toString() {
return "EntityElementGraph(collection=" + collectionPersister.getRole() + ", type=" + elementPersister.getEntityName() + ")"; return "EntityElementGraph(collection=" + collectionPersister.getRole() + ", type=" + elementPersister.getEntityName() + ")";
} }
@Override
protected FetchOwnerDelegate getFetchOwnerDelegate() {
return fetchOwnerDelegate;
}
} }

View File

@ -32,21 +32,19 @@ import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.FetchTiming; import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.spi.EntityKey; import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
import org.hibernate.loader.spi.ResultSetProcessingContext; import org.hibernate.loader.spi.ResultSetProcessingContext;
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.type.EntityType; import org.hibernate.type.EntityType;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class EntityFetch extends AbstractSingularAttributeFetch implements EntityReference { public class EntityFetch extends AbstractSingularAttributeFetch implements EntityReference, Fetch {
private final EntityType associationType; private final EntityType associationType;
private final EntityPersister persister; private final EntityPersister persister;
private final LockMode lockMode;
private final FetchOwnerDelegate fetchOwnerDelegate;
private IdentifierDescription identifierDescription; private IdentifierDescription identifierDescription;
@ -57,10 +55,12 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit
String ownerProperty, String ownerProperty,
EntityType entityType, EntityType entityType,
FetchStrategy fetchStrategy) { FetchStrategy fetchStrategy) {
super( sessionFactory, lockMode, owner, ownerProperty, fetchStrategy ); super( sessionFactory, owner, ownerProperty, fetchStrategy );
this.associationType = entityType; this.associationType = entityType;
this.persister = sessionFactory.getEntityPersister( associationType.getAssociatedEntityName() ); this.persister = sessionFactory.getEntityPersister( associationType.getAssociatedEntityName() );
this.lockMode = lockMode;
this.fetchOwnerDelegate = new EntityFetchOwnerDelegate( persister );
} }
/** /**
@ -73,6 +73,8 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit
super( original, copyContext, fetchOwnerCopy ); super( original, copyContext, fetchOwnerCopy );
this.associationType = original.associationType; this.associationType = original.associationType;
this.persister = original.persister; this.persister = original.persister;
this.lockMode = original.lockMode;
this.fetchOwnerDelegate = original.fetchOwnerDelegate;
} }
public EntityType getAssociationType() { public EntityType getAssociationType() {
@ -94,45 +96,16 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit
return identifierDescription; return identifierDescription;
} }
@Override
public LockMode getLockMode() {
return lockMode;
}
@Override @Override
public EntityPersister retrieveFetchSourcePersister() { public EntityPersister retrieveFetchSourcePersister() {
return persister; return persister;
} }
@Override
public CollectionFetch buildCollectionFetch(
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy,
LoadPlanBuildingContext loadPlanBuildingContext) {
return LoadPlanBuildingHelper.buildStandardCollectionFetch(
this,
attributeDefinition,
fetchStrategy,
loadPlanBuildingContext
);
}
@Override
public EntityFetch buildEntityFetch(
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy,
LoadPlanBuildingContext loadPlanBuildingContext) {
return LoadPlanBuildingHelper.buildStandardEntityFetch(
this,
attributeDefinition,
fetchStrategy,
loadPlanBuildingContext
);
}
@Override
public CompositeFetch buildCompositeFetch(
CompositionDefinition attributeDefinition,
LoadPlanBuildingContext loadPlanBuildingContext) {
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
}
@Override @Override
public void injectIdentifierDescription(IdentifierDescription identifierDescription) { public void injectIdentifierDescription(IdentifierDescription identifierDescription) {
this.identifierDescription = identifierDescription; this.identifierDescription = identifierDescription;
@ -268,4 +241,9 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit
copyContext.getReturnGraphVisitationStrategy().finishingEntityFetch( this ); copyContext.getReturnGraphVisitationStrategy().finishingEntityFetch( this );
return copy; return copy;
} }
@Override
protected FetchOwnerDelegate getFetchOwnerDelegate() {
return fetchOwnerDelegate;
}
} }

View File

@ -0,0 +1,72 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.loader.plan.spi;
import org.hibernate.engine.internal.JoinHelper;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.type.AssociationType;
import org.hibernate.type.Type;
/**
* @author Gail Badner
*/
public class EntityFetchOwnerDelegate implements FetchOwnerDelegate {
private final EntityPersister entityPersister;
public EntityFetchOwnerDelegate(EntityPersister entityPersister) {
this.entityPersister = entityPersister;
}
@Override
public boolean isNullable(Fetch fetch) {
return entityPersister.getPropertyNullability()[ determinePropertyIndex( fetch ) ];
}
@Override
public Type getType(Fetch fetch) {
return entityPersister.getPropertyTypes()[ determinePropertyIndex( fetch ) ];
}
@Override
public String[] getColumnNames(Fetch fetch) {
final OuterJoinLoadable outerJoinLoadable = (OuterJoinLoadable) entityPersister;
Type fetchType = getType( fetch );
if ( fetchType.isAssociationType() ) {
return JoinHelper.getLHSColumnNames(
(AssociationType) fetchType,
determinePropertyIndex( fetch ),
outerJoinLoadable,
outerJoinLoadable.getFactory()
);
}
else {
return outerJoinLoadable.getPropertyColumnNames( determinePropertyIndex( fetch ) );
}
}
private int determinePropertyIndex(Fetch fetch) {
return entityPersister.getEntityMetamodel().getPropertyIndex( fetch.getOwnerPropertyName() );
}
}

View File

@ -23,33 +23,24 @@
*/ */
package org.hibernate.loader.plan.spi; package org.hibernate.loader.plan.spi;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.engine.FetchStrategy; import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.PropertyPath; import org.hibernate.loader.PropertyPath;
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.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.type.AssociationType; import org.hibernate.type.AssociationType;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class EntityIndexGraph extends AbstractPlanNode implements FetchableCollectionIndex, EntityReference { public class EntityIndexGraph extends AbstractFetchOwner implements FetchableCollectionIndex, EntityReference {
private final CollectionReference collectionReference; private final CollectionReference collectionReference;
private final CollectionPersister collectionPersister; private final CollectionPersister collectionPersister;
private final AssociationType indexType; private final AssociationType indexType;
private final EntityPersister indexPersister; private final EntityPersister indexPersister;
private final PropertyPath propertyPath; private final PropertyPath propertyPath;
private final FetchOwnerDelegate fetchOwnerDelegate;
private List<Fetch> fetches;
private IdentifierDescription identifierDescription; private IdentifierDescription identifierDescription;
@ -63,28 +54,17 @@ public class EntityIndexGraph extends AbstractPlanNode implements FetchableColle
this.indexType = (AssociationType) collectionPersister.getIndexType(); this.indexType = (AssociationType) collectionPersister.getIndexType();
this.indexPersister = (EntityPersister) this.indexType.getAssociatedJoinable( sessionFactory() ); this.indexPersister = (EntityPersister) this.indexType.getAssociatedJoinable( sessionFactory() );
this.propertyPath = collectionPath.append( "<index>" ); // todo : do we want the <index> part? this.propertyPath = collectionPath.append( "<index>" ); // todo : do we want the <index> part?
this.fetchOwnerDelegate = new EntityFetchOwnerDelegate( indexPersister );
} }
public EntityIndexGraph(EntityIndexGraph original, CopyContext copyContext) { public EntityIndexGraph(EntityIndexGraph original, CopyContext copyContext) {
super( original ); super( original, copyContext );
this.collectionReference = original.collectionReference; this.collectionReference = original.collectionReference;
this.collectionPersister = original.collectionReference.getCollectionPersister(); this.collectionPersister = original.collectionReference.getCollectionPersister();
this.indexType = original.indexType; this.indexType = original.indexType;
this.indexPersister = original.indexPersister; this.indexPersister = original.indexPersister;
this.propertyPath = original.propertyPath; this.propertyPath = original.propertyPath;
this.fetchOwnerDelegate = original.fetchOwnerDelegate;
copyContext.getReturnGraphVisitationStrategy().startingFetches( original );
if ( fetches == null || fetches.size() == 0 ) {
this.fetches = Collections.emptyList();
}
else {
List<Fetch> fetchesCopy = new ArrayList<Fetch>();
for ( Fetch fetch : fetches ) {
fetchesCopy.add( fetch.makeCopy( copyContext, this ) );
}
this.fetches = fetchesCopy;
}
copyContext.getReturnGraphVisitationStrategy().finishingFetches( original );
} }
@Override @Override
@ -107,19 +87,6 @@ public class EntityIndexGraph extends AbstractPlanNode implements FetchableColle
return identifierDescription; return identifierDescription;
} }
@Override
public void addFetch(Fetch fetch) {
if ( fetches == null ) {
fetches = new ArrayList<Fetch>();
}
fetches.add( fetch );
}
@Override
public Fetch[] getFetches() {
return fetches == null ? NO_FETCHES : fetches.toArray( new Fetch[ fetches.size() ] );
}
@Override @Override
public void validateFetchPlan(FetchStrategy fetchStrategy) { public void validateFetchPlan(FetchStrategy fetchStrategy) {
} }
@ -134,39 +101,6 @@ public class EntityIndexGraph extends AbstractPlanNode implements FetchableColle
return propertyPath; return propertyPath;
} }
@Override
public CollectionFetch buildCollectionFetch(
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy,
LoadPlanBuildingContext loadPlanBuildingContext) {
return LoadPlanBuildingHelper.buildStandardCollectionFetch(
this,
attributeDefinition,
fetchStrategy,
loadPlanBuildingContext
);
}
@Override
public EntityFetch buildEntityFetch(
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy,
LoadPlanBuildingContext loadPlanBuildingContext) {
return LoadPlanBuildingHelper.buildStandardEntityFetch(
this,
attributeDefinition,
fetchStrategy,
loadPlanBuildingContext
);
}
@Override
public CompositeFetch buildCompositeFetch(
CompositionDefinition attributeDefinition,
LoadPlanBuildingContext loadPlanBuildingContext) {
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
}
@Override @Override
public void injectIdentifierDescription(IdentifierDescription identifierDescription) { public void injectIdentifierDescription(IdentifierDescription identifierDescription) {
this.identifierDescription = identifierDescription; this.identifierDescription = identifierDescription;
@ -176,4 +110,9 @@ public class EntityIndexGraph extends AbstractPlanNode implements FetchableColle
public EntityIndexGraph makeCopy(CopyContext copyContext) { public EntityIndexGraph makeCopy(CopyContext copyContext) {
return new EntityIndexGraph( this, copyContext ); return new EntityIndexGraph( this, copyContext );
} }
@Override
protected FetchOwnerDelegate getFetchOwnerDelegate() {
return fetchOwnerDelegate;
}
} }

View File

@ -32,12 +32,8 @@ import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.spi.EntityKey; import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.PropertyPath; import org.hibernate.loader.PropertyPath;
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
import org.hibernate.loader.spi.ResultSetProcessingContext; import org.hibernate.loader.spi.ResultSetProcessingContext;
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 static org.hibernate.loader.spi.ResultSetProcessingContext.IdentifierResolutionContext; import static org.hibernate.loader.spi.ResultSetProcessingContext.IdentifierResolutionContext;
@ -50,24 +46,32 @@ public class EntityReturn extends AbstractFetchOwner implements Return, EntityRe
private final PropertyPath propertyPath = new PropertyPath(); // its a root private final PropertyPath propertyPath = new PropertyPath(); // its a root
private final LockMode lockMode;
private final FetchOwnerDelegate fetchOwnerDelegate;
private IdentifierDescription identifierDescription; private IdentifierDescription identifierDescription;
public EntityReturn( public EntityReturn(
SessionFactoryImplementor sessionFactory, SessionFactoryImplementor sessionFactory,
LockMode lockMode, LockMode lockMode,
String entityName) { String entityName) {
super( sessionFactory, lockMode ); super( sessionFactory );
this.persister = sessionFactory.getEntityPersister( entityName ); this.persister = sessionFactory.getEntityPersister( entityName );
this.lockMode = lockMode;
this.fetchOwnerDelegate = new EntityFetchOwnerDelegate( persister );
} }
protected EntityReturn(EntityReturn original, CopyContext copyContext) { protected EntityReturn(EntityReturn original, CopyContext copyContext) {
super( original, copyContext ); super( original, copyContext );
this.persister = original.persister; this.persister = original.persister;
this.lockMode = original.lockMode;
this.fetchOwnerDelegate = original.fetchOwnerDelegate;
} }
@Override @Override
public LockMode getLockMode() { public LockMode getLockMode() {
return super.getLockMode(); return lockMode;
} }
@Override @Override
@ -99,39 +103,6 @@ public class EntityReturn extends AbstractFetchOwner implements Return, EntityRe
return propertyPath; return propertyPath;
} }
@Override
public CollectionFetch buildCollectionFetch(
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy,
LoadPlanBuildingContext loadPlanBuildingContext) {
return LoadPlanBuildingHelper.buildStandardCollectionFetch(
this,
attributeDefinition,
fetchStrategy,
loadPlanBuildingContext
);
}
@Override
public EntityFetch buildEntityFetch(
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy,
LoadPlanBuildingContext loadPlanBuildingContext) {
return LoadPlanBuildingHelper.buildStandardEntityFetch(
this,
attributeDefinition,
fetchStrategy,
loadPlanBuildingContext
);
}
@Override
public CompositeFetch buildCompositeFetch(
CompositionDefinition attributeDefinition,
LoadPlanBuildingContext loadPlanBuildingContext) {
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
}
@Override @Override
public void hydrate(ResultSet resultSet, ResultSetProcessingContext context) throws SQLException { public void hydrate(ResultSet resultSet, ResultSetProcessingContext context) throws SQLException {
EntityKey entityKey = getEntityKeyFromContext( context ); EntityKey entityKey = getEntityKeyFromContext( context );
@ -207,4 +178,9 @@ public class EntityReturn extends AbstractFetchOwner implements Return, EntityRe
public EntityReturn makeCopy(CopyContext copyContext) { public EntityReturn makeCopy(CopyContext copyContext) {
return new EntityReturn( this, copyContext ); return new EntityReturn( this, copyContext );
} }
@Override
protected FetchOwnerDelegate getFetchOwnerDelegate() {
return fetchOwnerDelegate;
}
} }

View File

@ -52,6 +52,10 @@ public interface Fetch extends CopyableFetch {
*/ */
public String getOwnerPropertyName(); public String getOwnerPropertyName();
public boolean isNullable();
public String[] getColumnNames();
public FetchStrategy getFetchStrategy(); public FetchStrategy getFetchStrategy();
/** /**

View File

@ -29,6 +29,7 @@ import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
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.persister.walking.spi.CompositionDefinition; import org.hibernate.persister.walking.spi.CompositionDefinition;
import org.hibernate.type.Type;
/** /**
* Contract for owners of fetches. Any non-scalar return could be a fetch owner. * Contract for owners of fetches. Any non-scalar return could be a fetch owner.
@ -56,6 +57,12 @@ public interface FetchOwner {
*/ */
public Fetch[] getFetches(); public Fetch[] getFetches();
public Type getType(Fetch fetch);
public boolean isNullable(Fetch fetch);
public String[] getColumnNames(Fetch fetch);
/** /**
* Is the asserted plan valid from this owner to a fetch? * Is the asserted plan valid from this owner to a fetch?
* *

View File

@ -0,0 +1,38 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.loader.plan.spi;
import org.hibernate.type.Type;
/**
* @author Gail Badner
*/
public interface FetchOwnerDelegate {
public boolean isNullable(Fetch fetch);
public Type getType(Fetch fetch);
public String[] getColumnNames(Fetch fetch);
}

View File

@ -23,10 +23,14 @@
*/ */
package org.hibernate.loader.plan.spi; package org.hibernate.loader.plan.spi;
import org.hibernate.persister.collection.CollectionPersister;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface FetchableCollectionElement extends FetchOwner, CopyableReturn { public interface FetchableCollectionElement extends FetchOwner, CopyableReturn {
@Override @Override
public FetchableCollectionElement makeCopy(CopyContext copyContext); public FetchableCollectionElement makeCopy(CopyContext copyContext);
public CollectionReference getCollectionReference();
} }

View File

@ -49,16 +49,20 @@ import org.hibernate.loader.plan.spi.AbstractSingularAttributeFetch;
import org.hibernate.loader.plan.spi.CollectionFetch; import org.hibernate.loader.plan.spi.CollectionFetch;
import org.hibernate.loader.plan.spi.CollectionReference; import org.hibernate.loader.plan.spi.CollectionReference;
import org.hibernate.loader.plan.spi.CollectionReturn; import org.hibernate.loader.plan.spi.CollectionReturn;
import org.hibernate.loader.plan.spi.CompositeElementGraph;
import org.hibernate.loader.plan.spi.CompositeFetch; import org.hibernate.loader.plan.spi.CompositeFetch;
import org.hibernate.loader.plan.spi.CompositeFetchOwnerDelegate;
import org.hibernate.loader.plan.spi.EntityFetch; import org.hibernate.loader.plan.spi.EntityFetch;
import org.hibernate.loader.plan.spi.EntityReference; import org.hibernate.loader.plan.spi.EntityReference;
import org.hibernate.loader.plan.spi.EntityReturn; import org.hibernate.loader.plan.spi.EntityReturn;
import org.hibernate.loader.plan.spi.Fetch; import org.hibernate.loader.plan.spi.Fetch;
import org.hibernate.loader.plan.spi.FetchOwner; import org.hibernate.loader.plan.spi.FetchOwner;
import org.hibernate.loader.plan.spi.FetchOwnerDelegate;
import org.hibernate.loader.plan.spi.IdentifierDescription; import org.hibernate.loader.plan.spi.IdentifierDescription;
import org.hibernate.loader.plan.spi.Return; import org.hibernate.loader.plan.spi.Return;
import org.hibernate.loader.spi.ResultSetProcessingContext; import org.hibernate.loader.spi.ResultSetProcessingContext;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Loadable;
import org.hibernate.persister.spi.HydratedCompoundValueHandler; import org.hibernate.persister.spi.HydratedCompoundValueHandler;
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;
@ -66,9 +70,11 @@ import org.hibernate.persister.walking.spi.CollectionDefinition;
import org.hibernate.persister.walking.spi.CollectionElementDefinition; import org.hibernate.persister.walking.spi.CollectionElementDefinition;
import org.hibernate.persister.walking.spi.CollectionIndexDefinition; import org.hibernate.persister.walking.spi.CollectionIndexDefinition;
import org.hibernate.persister.walking.spi.CompositionDefinition; import org.hibernate.persister.walking.spi.CompositionDefinition;
import org.hibernate.persister.walking.spi.CompositionElementDefinition;
import org.hibernate.persister.walking.spi.EntityDefinition; import org.hibernate.persister.walking.spi.EntityDefinition;
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition; import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
import org.hibernate.persister.walking.spi.WalkingException; import org.hibernate.persister.walking.spi.WalkingException;
import org.hibernate.type.CompositeType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import static org.hibernate.loader.spi.ResultSetProcessingContext.IdentifierResolutionContext; import static org.hibernate.loader.spi.ResultSetProcessingContext.IdentifierResolutionContext;
@ -192,7 +198,12 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
final FetchOwner identifierAttributeCollector; final FetchOwner identifierAttributeCollector;
if ( entityIdentifierDefinition.isEncapsulated() ) { if ( entityIdentifierDefinition.isEncapsulated() ) {
identifierAttributeCollector = new EncapsulatedIdentifierAttributeCollector( entityReference ); if ( entityIdentifierDefinition.getEntityDefinition().getEntityPersister().getIdentifierType().isComponentType() ) {
identifierAttributeCollector = new EncapsulatedCompositeIdentifierAttributeCollector( entityReference );
}
else {
identifierAttributeCollector = new EncapsulatedIdentifierAttributeCollector( entityReference );
}
} }
else { else {
identifierAttributeCollector = new NonEncapsulatedIdentifierAttributeCollector( entityReference ); identifierAttributeCollector = new NonEncapsulatedIdentifierAttributeCollector( entityReference );
@ -307,6 +318,35 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
// - the element graph pushed while starting would be popped in finishing/Entity/finishingComposite // - the element graph pushed while starting would be popped in finishing/Entity/finishingComposite
} }
@Override
public void startingCompositeElement(CompositionElementDefinition compositeElementDefinition) {
System.out.println(
String.format(
"%s Starting composite collection element for (%s)",
StringHelper.repeat( ">>", fetchOwnerStack.size() ),
compositeElementDefinition.getCollectionDefinition().getCollectionPersister().getRole()
)
);
}
@Override
public void finishingCompositeElement(CompositionElementDefinition compositeElementDefinition) {
// pop the current fetch owner, and make sure what we just popped represents this composition
final FetchOwner poppedFetchOwner = popFromStack();
if ( ! CompositeElementGraph.class.isInstance( poppedFetchOwner ) ) {
throw new WalkingException( "Mismatched FetchOwner from stack on pop" );
}
// NOTE : not much else we can really check here atm since on the walking spi side we do not have path
log.tracef(
"%s Finished composite element for : %s",
StringHelper.repeat( "<<", fetchOwnerStack.size() ),
compositeElementDefinition.getCollectionDefinition().getCollectionPersister().getRole()
);
}
@Override @Override
public void finishingCollection(CollectionDefinition collectionDefinition) { public void finishingCollection(CollectionDefinition collectionDefinition) {
// pop the current fetch owner, and make sure what we just popped represents this collection // pop the current fetch owner, and make sure what we just popped represents this collection
@ -513,6 +553,11 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
return entityReference.getEntityPersister(); return entityReference.getEntityPersister();
} }
@Override
public boolean isNullable(Fetch fetch) {
return false;
}
@Override @Override
public IdentifierDescription getIdentifierDescription() { public IdentifierDescription getIdentifierDescription() {
return entityReference.getIdentifierDescription(); return entityReference.getIdentifierDescription();
@ -596,6 +641,13 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
} }
} }
protected static abstract class AbstractCompositeIdentifierAttributeCollector extends AbstractIdentifierAttributeCollector {
public AbstractCompositeIdentifierAttributeCollector(EntityReference entityReference) {
super( entityReference );
}
}
protected static class EncapsulatedIdentifierAttributeCollector extends AbstractIdentifierAttributeCollector { protected static class EncapsulatedIdentifierAttributeCollector extends AbstractIdentifierAttributeCollector {
private final PropertyPath propertyPath; private final PropertyPath propertyPath;
@ -613,17 +665,76 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
); );
} }
@Override
public Type getType(Fetch fetch) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public String[] getColumnNames(Fetch fetch) {
return ( (Loadable) entityReference.getEntityPersister() ).getIdentifierColumnNames();
}
@Override @Override
public PropertyPath getPropertyPath() { public PropertyPath getPropertyPath() {
return propertyPath; return propertyPath;
} }
} }
protected static class NonEncapsulatedIdentifierAttributeCollector extends AbstractIdentifierAttributeCollector { protected static class EncapsulatedCompositeIdentifierAttributeCollector extends AbstractCompositeIdentifierAttributeCollector {
private final PropertyPath propertyPath; private final PropertyPath propertyPath;
public EncapsulatedCompositeIdentifierAttributeCollector(EntityReference entityReference) {
super( entityReference );
this.propertyPath = ( (FetchOwner) entityReference ).getPropertyPath();
}
@Override
protected IdentifierDescription buildIdentifierDescription() {
return new IdentifierDescriptionImpl(
entityReference,
identifierFetches.toArray( new AbstractSingularAttributeFetch[ identifierFetches.size() ] ),
null
);
}
@Override
public PropertyPath getPropertyPath() {
return propertyPath;
}
@Override
public Type getType(Fetch fetch) {
if ( !fetch.getOwnerPropertyName().equals( entityReference.getEntityPersister().getIdentifierPropertyName() ) ) {
throw new IllegalArgumentException(
String.format(
"Fetch owner property name [%s] is not the same as the identifier property name [%s].",
fetch.getOwnerPropertyName(),
entityReference.getEntityPersister().getIdentifierPropertyName()
)
);
}
return entityReference.getEntityPersister().getIdentifierType();
}
@Override
public String[] getColumnNames(Fetch fetch) {
return ( (Loadable) entityReference.getEntityPersister() ).getIdentifierColumnNames();
}
}
protected static class NonEncapsulatedIdentifierAttributeCollector extends AbstractCompositeIdentifierAttributeCollector {
private final PropertyPath propertyPath;
private final FetchOwnerDelegate fetchOwnerDelegate;
public NonEncapsulatedIdentifierAttributeCollector(EntityReference entityReference) { public NonEncapsulatedIdentifierAttributeCollector(EntityReference entityReference) {
super( entityReference ); super( entityReference );
this.propertyPath = ( (FetchOwner) entityReference ).getPropertyPath().append( "<id>" ); this.propertyPath = ( (FetchOwner) entityReference ).getPropertyPath().append( "<id>" );
this.fetchOwnerDelegate = new CompositeFetchOwnerDelegate(
entityReference.getEntityPersister().getFactory(),
(CompositeType) entityReference.getEntityPersister().getIdentifierType(),
( (Loadable) entityReference.getEntityPersister() ).getIdentifierColumnNames()
);
} }
@Override @Override
@ -639,6 +750,24 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
public PropertyPath getPropertyPath() { public PropertyPath getPropertyPath() {
return propertyPath; return propertyPath;
} }
public Type getType(Fetch fetch) {
if ( !fetch.getOwnerPropertyName().equals( entityReference.getEntityPersister().getIdentifierPropertyName() ) ) {
throw new IllegalArgumentException(
String.format(
"Fetch owner property name [%s] is not the same as the identifier property name [%s].",
fetch.getOwnerPropertyName(),
entityReference.getEntityPersister().getIdentifierPropertyName()
)
);
}
return fetchOwnerDelegate.getType( fetch );
}
public String[] getColumnNames(Fetch fetch) {
return fetchOwnerDelegate.getColumnNames( fetch );
}
} }
private static class IdentifierDescriptionImpl implements IdentifierDescription { private static class IdentifierDescriptionImpl implements IdentifierDescription {

View File

@ -80,10 +80,14 @@ import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Loadable; import org.hibernate.persister.entity.Loadable;
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.internal.CompositionSingularSubAttributesHelper;
import org.hibernate.persister.walking.spi.AttributeDefinition;
import org.hibernate.persister.walking.spi.AttributeSource;
import org.hibernate.persister.walking.spi.CollectionDefinition; import org.hibernate.persister.walking.spi.CollectionDefinition;
import org.hibernate.persister.walking.spi.CollectionElementDefinition; import org.hibernate.persister.walking.spi.CollectionElementDefinition;
import org.hibernate.persister.walking.spi.CollectionIndexDefinition; import org.hibernate.persister.walking.spi.CollectionIndexDefinition;
import org.hibernate.persister.walking.spi.CompositionDefinition; import org.hibernate.persister.walking.spi.CompositionDefinition;
import org.hibernate.persister.walking.spi.CompositionElementDefinition;
import org.hibernate.persister.walking.spi.EntityDefinition; import org.hibernate.persister.walking.spi.EntityDefinition;
import org.hibernate.pretty.MessageHelper; import org.hibernate.pretty.MessageHelper;
import org.hibernate.sql.Alias; import org.hibernate.sql.Alias;
@ -1941,7 +1945,6 @@ public abstract class AbstractCollectionPersister
public abstract FilterAliasGenerator getFilterAliasGenerator(final String rootAlias); public abstract FilterAliasGenerator getFilterAliasGenerator(final String rootAlias);
// ColectionDefinition impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ColectionDefinition impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override @Override
@ -2007,12 +2010,42 @@ public abstract class AbstractCollectionPersister
} }
@Override @Override
public CompositionDefinition toCompositeDefinition() { public CompositionElementDefinition toCompositeElementDefinition() {
final String propertyName = role.substring( entityName.length() + 1 );
final int propertyIndex = ownerPersister.getEntityMetamodel().getPropertyIndex( propertyName );
if ( ! getType().isComponentType() ) { if ( ! getType().isComponentType() ) {
throw new IllegalStateException( "Cannot treat entity collection element type as composite" ); throw new IllegalStateException( "Cannot treat entity collection element type as composite" );
} }
// todo : implement
throw new NotYetImplementedException(); return new CompositionElementDefinition() {
@Override
public String getName() {
return "";
}
@Override
public Type getType() {
return getElementType();
}
@Override
public AttributeSource getSource() {
// TODO: what if this is a collection w/in an encapsulated composition attribute?
// should return the encapsulated composition attribute instead???
return getOwnerEntityPersister();
}
@Override
public Iterable<AttributeDefinition> getAttributes() {
return CompositionSingularSubAttributesHelper.getCompositionElementSubAttributes( this );
}
@Override
public CollectionDefinition getCollectionDefinition() {
return AbstractCollectionPersister.this;
}
};
} }
}; };
} }

View File

@ -59,7 +59,6 @@ import org.hibernate.cache.spi.entry.ReferenceCacheEntryImpl;
import org.hibernate.cache.spi.entry.StandardCacheEntryImpl; import org.hibernate.cache.spi.entry.StandardCacheEntryImpl;
import org.hibernate.cache.spi.entry.StructuredCacheEntry; import org.hibernate.cache.spi.entry.StructuredCacheEntry;
import org.hibernate.cache.spi.entry.UnstructuredCacheEntry; import org.hibernate.cache.spi.entry.UnstructuredCacheEntry;
import org.hibernate.cfg.NotYetImplementedException;
import org.hibernate.dialect.lock.LockingStrategy; import org.hibernate.dialect.lock.LockingStrategy;
import org.hibernate.engine.OptimisticLockStyle; import org.hibernate.engine.OptimisticLockStyle;
import org.hibernate.engine.internal.StatefulPersistenceContext; import org.hibernate.engine.internal.StatefulPersistenceContext;
@ -111,12 +110,7 @@ import org.hibernate.metamodel.relational.DerivedValue;
import org.hibernate.metamodel.relational.Value; import org.hibernate.metamodel.relational.Value;
import org.hibernate.persister.walking.internal.EntityIdentifierDefinitionHelper; import org.hibernate.persister.walking.internal.EntityIdentifierDefinitionHelper;
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.CompositionDefinition;
import org.hibernate.persister.walking.spi.EncapsulatedEntityIdentifierDefinition;
import org.hibernate.persister.walking.spi.EntityDefinition;
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition; import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
import org.hibernate.persister.walking.spi.NonEncapsulatedEntityIdentifierDefinition;
import org.hibernate.pretty.MessageHelper; import org.hibernate.pretty.MessageHelper;
import org.hibernate.property.BackrefPropertyAccessor; import org.hibernate.property.BackrefPropertyAccessor;
import org.hibernate.sql.Alias; import org.hibernate.sql.Alias;
@ -132,7 +126,6 @@ import org.hibernate.sql.Update;
import org.hibernate.tuple.entity.EntityMetamodel; import org.hibernate.tuple.entity.EntityMetamodel;
import org.hibernate.tuple.entity.EntityTuplizer; import org.hibernate.tuple.entity.EntityTuplizer;
import org.hibernate.type.AssociationType; import org.hibernate.type.AssociationType;
import org.hibernate.type.ComponentType;
import org.hibernate.type.CompositeType; import org.hibernate.type.CompositeType;
import org.hibernate.type.EntityType; import org.hibernate.type.EntityType;
import org.hibernate.type.Type; import org.hibernate.type.Type;

View File

@ -0,0 +1,212 @@
package org.hibernate.persister.walking.internal;
import java.util.Iterator;
import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.CascadeStyles;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.loader.PropertyPath;
import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.persister.entity.AbstractEntityPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.persister.spi.HydratedCompoundValueHandler;
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
import org.hibernate.persister.walking.spi.AssociationKey;
import org.hibernate.persister.walking.spi.AttributeDefinition;
import org.hibernate.persister.walking.spi.AttributeSource;
import org.hibernate.persister.walking.spi.CollectionDefinition;
import org.hibernate.persister.walking.spi.CompositionDefinition;
import org.hibernate.persister.walking.spi.CompositionElementDefinition;
import org.hibernate.persister.walking.spi.EntityDefinition;
import org.hibernate.persister.walking.spi.WalkingException;
import org.hibernate.type.AssociationType;
import org.hibernate.type.CompositeType;
import org.hibernate.type.Type;
/**
* @author Gail Badner
*/
public class CompositionSingularSubAttributesHelper {
public static Iterable<AttributeDefinition> getIdentifierSubAttributes(
final AbstractEntityPersister entityPersister) {
return getSingularSubAttributes(
entityPersister,
entityPersister,
(CompositeType) entityPersister.getIdentifierType(),
entityPersister.getTableName(),
entityPersister.getRootTableIdentifierColumnNames()
);
}
public static Iterable<AttributeDefinition> getCompositionElementSubAttributes(
CompositionElementDefinition compositionElementDefinition) {
final QueryableCollection collectionPersister =
(QueryableCollection) compositionElementDefinition.getCollectionDefinition().getCollectionPersister();
return getSingularSubAttributes(
compositionElementDefinition.getSource(),
(OuterJoinLoadable) collectionPersister.getOwnerEntityPersister(),
(CompositeType) collectionPersister.getElementType(),
collectionPersister.getTableName(),
collectionPersister.getElementColumnNames()
);
}
private static Iterable<AttributeDefinition> getSingularSubAttributes(
final AttributeSource source,
final OuterJoinLoadable ownerEntityPersister,
final CompositeType compositeType,
final String lhsTableName,
final String[] lhsColumns) {
return new Iterable<AttributeDefinition>() {
@Override
public Iterator<AttributeDefinition> iterator() {
return new Iterator<AttributeDefinition>() {
private final int numberOfAttributes = compositeType.getSubtypes().length;
private int currentSubAttributeNumber = 0;
private int currentColumnPosition = 0;
@Override
public boolean hasNext() {
return currentSubAttributeNumber < numberOfAttributes;
}
@Override
public AttributeDefinition next() {
final int subAttributeNumber = currentSubAttributeNumber;
currentSubAttributeNumber++;
final String name = compositeType.getPropertyNames()[subAttributeNumber];
final Type type = compositeType.getSubtypes()[subAttributeNumber];
final int columnPosition = currentColumnPosition;
final int columnSpan = type.getColumnSpan( ownerEntityPersister.getFactory() );
final String[] subAttributeLhsColumns = ArrayHelper.slice( lhsColumns, columnPosition, columnSpan );
currentColumnPosition += columnSpan;
if ( type.isAssociationType() ) {
final AssociationType aType = (AssociationType) type;
return new AssociationAttributeDefinition() {
@Override
public AssociationKey getAssociationKey() {
/* TODO: is this always correct? */
//return new AssociationKey(
// joinable.getTableName(),
// JoinHelper.getRHSColumnNames( aType, getEntityPersister().getFactory() )
//);
return new AssociationKey(
lhsTableName,
subAttributeLhsColumns
);
}
@Override
public boolean isCollection() {
return false;
}
@Override
public EntityDefinition toEntityDefinition() {
return (EntityPersister) aType.getAssociatedJoinable( ownerEntityPersister.getFactory() );
}
@Override
public CollectionDefinition toCollectionDefinition() {
throw new WalkingException( "A collection cannot be mapped to a composite ID sub-attribute." );
}
@Override
public FetchStrategy determineFetchPlan(LoadQueryInfluencers loadQueryInfluencers, PropertyPath propertyPath) {
return new FetchStrategy( FetchTiming.IMMEDIATE, FetchStyle.JOIN );
}
@Override
public CascadeStyle determineCascadeStyle() {
return CascadeStyles.NONE;
}
@Override
public HydratedCompoundValueHandler getHydratedCompoundValueExtractor() {
return null;
}
@Override
public String getName() {
return name;
}
@Override
public Type getType() {
return type;
}
@Override
public AttributeSource getSource() {
return source;
}
};
}
else if ( type.isComponentType() ) {
return new CompositionDefinition() {
@Override
public String getName() {
return name;
}
@Override
public Type getType() {
return type;
}
@Override
public AttributeSource getSource() {
return this;
}
@Override
public Iterable<AttributeDefinition> getAttributes() {
return CompositionSingularSubAttributesHelper.getSingularSubAttributes(
this,
ownerEntityPersister,
(CompositeType) type,
lhsTableName,
subAttributeLhsColumns
);
}
};
}
else {
return new AttributeDefinition() {
@Override
public String getName() {
return name;
}
@Override
public Type getType() {
return type;
}
@Override
public AttributeSource getSource() {
return source;
}
};
}
}
@Override
public void remove() {
throw new UnsupportedOperationException( "Remove operation not supported here" );
}
};
}
};
}
}

View File

@ -23,37 +23,16 @@
*/ */
package org.hibernate.persister.walking.internal; package org.hibernate.persister.walking.internal;
import java.util.Iterator;
import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.CascadeStyles;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.loader.PropertyPath;
import org.hibernate.persister.entity.AbstractEntityPersister; import org.hibernate.persister.entity.AbstractEntityPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Joinable;
import org.hibernate.persister.spi.HydratedCompoundValueHandler;
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
import org.hibernate.persister.walking.spi.AssociationKey;
import org.hibernate.persister.walking.spi.AttributeDefinition; import org.hibernate.persister.walking.spi.AttributeDefinition;
import org.hibernate.persister.walking.spi.AttributeSource; import org.hibernate.persister.walking.spi.AttributeSource;
import org.hibernate.persister.walking.spi.CollectionDefinition;
import org.hibernate.persister.walking.spi.CompositionDefinition; import org.hibernate.persister.walking.spi.CompositionDefinition;
import org.hibernate.persister.walking.spi.EncapsulatedEntityIdentifierDefinition; import org.hibernate.persister.walking.spi.EncapsulatedEntityIdentifierDefinition;
import org.hibernate.persister.walking.spi.EntityDefinition; import org.hibernate.persister.walking.spi.EntityDefinition;
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition; import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
import org.hibernate.persister.walking.spi.NonEncapsulatedEntityIdentifierDefinition; import org.hibernate.persister.walking.spi.NonEncapsulatedEntityIdentifierDefinition;
import org.hibernate.persister.walking.spi.WalkingException;
import org.hibernate.type.AssociationType;
import org.hibernate.type.ComponentType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import static org.hibernate.engine.internal.JoinHelper.getLHSColumnNames;
import static org.hibernate.engine.internal.JoinHelper.getLHSTableName;
/** /**
* @author Gail Badner * @author Gail Badner
*/ */
@ -78,12 +57,13 @@ public class EntityIdentifierDefinitionHelper {
}; };
} }
public static EntityIdentifierDefinition buildEncapsulatedCompositeIdentifierDefinition(final AbstractEntityPersister entityPersister) { public static EntityIdentifierDefinition buildEncapsulatedCompositeIdentifierDefinition(
final AbstractEntityPersister entityPersister) {
return new EncapsulatedEntityIdentifierDefinition() { return new EncapsulatedEntityIdentifierDefinition() {
@Override @Override
public AttributeDefinition getAttributeDefinition() { public AttributeDefinition getAttributeDefinition() {
return new CompositeAttributeDefinitionAdapter( entityPersister ); return new CompositionDefinitionAdapter( entityPersister );
} }
@Override @Override
@ -102,7 +82,7 @@ public class EntityIdentifierDefinitionHelper {
return new NonEncapsulatedEntityIdentifierDefinition() { return new NonEncapsulatedEntityIdentifierDefinition() {
@Override @Override
public Iterable<AttributeDefinition> getAttributes() { public Iterable<AttributeDefinition> getAttributes() {
return new CompositeAttributeDefinitionAdapter( entityPersister ).getAttributes(); return CompositionSingularSubAttributesHelper.getIdentifierSubAttributes( entityPersister );
} }
@Override @Override
@ -154,160 +134,20 @@ public class EntityIdentifierDefinitionHelper {
} }
} }
private static class CompositeAttributeDefinitionAdapter extends AttributeDefinitionAdapter implements CompositionDefinition { private static class CompositionDefinitionAdapter extends AttributeDefinitionAdapter implements CompositionDefinition {
CompositeAttributeDefinitionAdapter(AbstractEntityPersister entityPersister) { CompositionDefinitionAdapter(AbstractEntityPersister entityPersister) {
super( entityPersister ); super( entityPersister );
} }
@Override
public String toString() {
return "<identifier-property:" + getName() + ">";
}
@Override @Override
public Iterable<AttributeDefinition> getAttributes() { public Iterable<AttributeDefinition> getAttributes() {
return new Iterable<AttributeDefinition>() { return CompositionSingularSubAttributesHelper.getIdentifierSubAttributes( getEntityPersister() );
@Override
public Iterator<AttributeDefinition> iterator() {
final ComponentType componentType = (ComponentType) getType();
return new Iterator<AttributeDefinition>() {
private final int numberOfAttributes = componentType.getSubtypes().length;
private int currentSubAttributeNumber = 0;
private int currentColumnPosition = 0;
@Override
public boolean hasNext() {
return currentSubAttributeNumber < numberOfAttributes;
}
@Override
public AttributeDefinition next() {
final int subAttributeNumber = currentSubAttributeNumber;
currentSubAttributeNumber++;
final AttributeSource source = getSource();
final String name = componentType.getPropertyNames()[subAttributeNumber];
final Type type = componentType.getSubtypes()[subAttributeNumber];
final int columnPosition = currentColumnPosition;
currentColumnPosition += type.getColumnSpan( getEntityPersister().getFactory() );
if ( type.isAssociationType() ) {
final AssociationType aType = (AssociationType) type;
final Joinable joinable = aType.getAssociatedJoinable( getEntityPersister().getFactory() );
return new AssociationAttributeDefinition() {
@Override
public AssociationKey getAssociationKey() {
/* TODO: is this always correct? */
//return new AssociationKey(
// joinable.getTableName(),
// JoinHelper.getRHSColumnNames( aType, getEntityPersister().getFactory() )
//);
return new AssociationKey(
getEntityPersister().getTableName(),
getLHSColumnNames(
aType,
-1,
columnPosition,
getEntityPersister(),
getEntityPersister().getFactory()
)
);
}
@Override
public boolean isCollection() {
return false;
}
@Override
public EntityDefinition toEntityDefinition() {
return (EntityPersister) joinable;
}
@Override
public CollectionDefinition toCollectionDefinition() {
throw new WalkingException( "A collection cannot be mapped to a composite ID sub-attribute." );
}
@Override
public FetchStrategy determineFetchPlan(LoadQueryInfluencers loadQueryInfluencers, PropertyPath propertyPath) {
return new FetchStrategy( FetchTiming.IMMEDIATE, FetchStyle.JOIN );
}
@Override
public CascadeStyle determineCascadeStyle() {
return CascadeStyles.NONE;
}
@Override
public HydratedCompoundValueHandler getHydratedCompoundValueExtractor() {
return null;
}
@Override
public String getName() {
return name;
}
@Override
public Type getType() {
return type;
}
@Override
public AttributeSource getSource() {
return source;
}
};
}
else if ( type.isComponentType() ) {
return new CompositionDefinition() {
@Override
public String getName() {
return name;
}
@Override
public Type getType() {
return type;
}
@Override
public AttributeSource getSource() {
return source;
}
@Override
public Iterable<AttributeDefinition> getAttributes() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
};
}
else {
return new AttributeDefinition() {
@Override
public String getName() {
return name;
}
@Override
public Type getType() {
return type;
}
@Override
public AttributeSource getSource() {
return source;
}
};
}
}
@Override
public void remove() {
throw new UnsupportedOperationException( "Remove operation not supported here" );
}
};
}
};
} }
} }
} }

View File

@ -55,6 +55,9 @@ public interface AssociationVisitationStrategy {
public void startingComposite(CompositionDefinition compositionDefinition); public void startingComposite(CompositionDefinition compositionDefinition);
public void finishingComposite(CompositionDefinition compositionDefinition); public void finishingComposite(CompositionDefinition compositionDefinition);
public void startingCompositeElement(CompositionElementDefinition compositionElementDefinition);
public void finishingCompositeElement(CompositionElementDefinition compositionElementDefinition);
public boolean startingAttribute(AttributeDefinition attributeDefinition); public boolean startingAttribute(AttributeDefinition attributeDefinition);
public void finishingAttribute(AttributeDefinition attributeDefinition); public void finishingAttribute(AttributeDefinition attributeDefinition);
} }

View File

@ -35,5 +35,5 @@ public interface CollectionElementDefinition {
public EntityDefinition toEntityDefinition(); public EntityDefinition toEntityDefinition();
public CompositionDefinition toCompositeDefinition(); public CompositionElementDefinition toCompositeElementDefinition();
} }

View File

@ -0,0 +1,31 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.persister.walking.spi;
/**
* @author Gail Badner
*/
public interface CompositionElementDefinition extends CompositionDefinition{
public CollectionDefinition getCollectionDefinition();
}

View File

@ -28,21 +28,12 @@ import java.util.Set;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.PropertyPath; import org.hibernate.loader.PropertyPath;
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.Joinable;
import org.hibernate.persister.spi.HydratedCompoundValueHandler;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import static org.hibernate.engine.internal.JoinHelper.getRHSColumnNames;
/** /**
* Provides model graph visitation based on the defined metadata (as opposed to based on the incoming graph * Provides model graph visitation based on the defined metadata (as opposed to based on the incoming graph
* as we see in cascade processing). In layman terms, we are walking the graph of the users model as defined by * as we see in cascade processing). In layman terms, we are walking the graph of the users model as defined by
@ -211,7 +202,7 @@ public class MetadataDrivenModelGraphVisitor {
strategy.startingCollectionElements( elementDefinition ); strategy.startingCollectionElements( elementDefinition );
if ( elementDefinition.getType().isComponentType() ) { if ( elementDefinition.getType().isComponentType() ) {
visitCompositeDefinition( elementDefinition.toCompositeDefinition() ); visitCompositeElementDefinition( elementDefinition.toCompositeElementDefinition() );
} }
else if ( elementDefinition.getType().isEntityType() ) { else if ( elementDefinition.getType().isEntityType() ) {
visitEntityDefinition( elementDefinition.toEntityDefinition() ); visitEntityDefinition( elementDefinition.toEntityDefinition() );
@ -220,6 +211,13 @@ public class MetadataDrivenModelGraphVisitor {
strategy.finishingCollectionElements( elementDefinition ); strategy.finishingCollectionElements( elementDefinition );
} }
private void visitCompositeElementDefinition(CompositionElementDefinition compositionElementDefinition) {
strategy.startingCompositeElement( compositionElementDefinition );
visitAttributes( compositionElementDefinition );
strategy.finishingCompositeElement( compositionElementDefinition );
}
private final Set<AssociationKey> visitedAssociationKeys = new HashSet<AssociationKey>(); private final Set<AssociationKey> visitedAssociationKeys = new HashSet<AssociationKey>();

View File

@ -39,7 +39,7 @@ public abstract class AbstractCompositeBasedAttribute
private final int ownerAttributeNumber; private final int ownerAttributeNumber;
public AbstractCompositeBasedAttribute( public AbstractCompositeBasedAttribute(
AbstractCompositionDefinition source, AbstractCompositionAttribute source,
SessionFactoryImplementor sessionFactory, SessionFactoryImplementor sessionFactory,
int attributeNumber, int attributeNumber,
String attributeName, String attributeName,
@ -55,7 +55,7 @@ public abstract class AbstractCompositeBasedAttribute
} }
@Override @Override
public AbstractCompositionDefinition getSource() { public AbstractCompositionAttribute getSource() {
return (AbstractCompositionDefinition) super.getSource(); return (AbstractCompositionAttribute) super.getSource();
} }
} }

View File

@ -48,9 +48,9 @@ import static org.hibernate.engine.internal.JoinHelper.getRHSColumnNames;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public abstract class AbstractCompositionDefinition extends AbstractNonIdentifierAttribute implements public abstract class AbstractCompositionAttribute extends AbstractNonIdentifierAttribute implements
CompositionDefinition { CompositionDefinition {
protected AbstractCompositionDefinition( protected AbstractCompositionAttribute(
AttributeSource source, AttributeSource source,
SessionFactoryImplementor sessionFactory, SessionFactoryImplementor sessionFactory,
int attributeNumber, int attributeNumber,
@ -120,41 +120,41 @@ public abstract class AbstractCompositionDefinition extends AbstractNonIdentifie
} }
return new CompositeBasedAssociationAttribute( return new CompositeBasedAssociationAttribute(
AbstractCompositionDefinition.this, AbstractCompositionAttribute.this,
sessionFactory(), sessionFactory(),
subAttributeNumber, subAttributeNumber,
name, name,
(AssociationType) type, (AssociationType) type,
new BaselineAttributeInformation.Builder() new BaselineAttributeInformation.Builder()
.setInsertable( AbstractCompositionDefinition.this.isInsertable() ) .setInsertable( AbstractCompositionAttribute.this.isInsertable() )
.setUpdateable( AbstractCompositionDefinition.this.isUpdateable() ) .setUpdateable( AbstractCompositionAttribute.this.isUpdateable() )
.setInsertGenerated( AbstractCompositionDefinition.this.isInsertGenerated() ) .setInsertGenerated( AbstractCompositionAttribute.this.isInsertGenerated() )
.setUpdateGenerated( AbstractCompositionDefinition.this.isUpdateGenerated() ) .setUpdateGenerated( AbstractCompositionAttribute.this.isUpdateGenerated() )
.setNullable( getType().getPropertyNullability()[subAttributeNumber] ) .setNullable( getType().getPropertyNullability()[subAttributeNumber] )
.setDirtyCheckable( true ) .setDirtyCheckable( true )
.setVersionable( AbstractCompositionDefinition.this.isVersionable() ) .setVersionable( AbstractCompositionAttribute.this.isVersionable() )
.setCascadeStyle( getType().getCascadeStyle( subAttributeNumber ) ) .setCascadeStyle( getType().getCascadeStyle( subAttributeNumber ) )
.setFetchMode( getType().getFetchMode( subAttributeNumber ) ) .setFetchMode( getType().getFetchMode( subAttributeNumber ) )
.createInformation(), .createInformation(),
AbstractCompositionDefinition.this.attributeNumber(), AbstractCompositionAttribute.this.attributeNumber(),
associationKey associationKey
); );
} }
else if ( type.isComponentType() ) { else if ( type.isComponentType() ) {
return new CompositionBasedCompositionAttribute( return new CompositionBasedCompositionAttribute(
AbstractCompositionDefinition.this, AbstractCompositionAttribute.this,
sessionFactory(), sessionFactory(),
subAttributeNumber, subAttributeNumber,
name, name,
(CompositeType) type, (CompositeType) type,
new BaselineAttributeInformation.Builder() new BaselineAttributeInformation.Builder()
.setInsertable( AbstractCompositionDefinition.this.isInsertable() ) .setInsertable( AbstractCompositionAttribute.this.isInsertable() )
.setUpdateable( AbstractCompositionDefinition.this.isUpdateable() ) .setUpdateable( AbstractCompositionAttribute.this.isUpdateable() )
.setInsertGenerated( AbstractCompositionDefinition.this.isInsertGenerated() ) .setInsertGenerated( AbstractCompositionAttribute.this.isInsertGenerated() )
.setUpdateGenerated( AbstractCompositionDefinition.this.isUpdateGenerated() ) .setUpdateGenerated( AbstractCompositionAttribute.this.isUpdateGenerated() )
.setNullable( getType().getPropertyNullability()[subAttributeNumber] ) .setNullable( getType().getPropertyNullability()[subAttributeNumber] )
.setDirtyCheckable( true ) .setDirtyCheckable( true )
.setVersionable( AbstractCompositionDefinition.this.isVersionable() ) .setVersionable( AbstractCompositionAttribute.this.isVersionable() )
.setCascadeStyle( getType().getCascadeStyle( subAttributeNumber ) ) .setCascadeStyle( getType().getCascadeStyle( subAttributeNumber ) )
.setFetchMode( getType().getFetchMode( subAttributeNumber ) ) .setFetchMode( getType().getFetchMode( subAttributeNumber ) )
.createInformation() .createInformation()
@ -162,19 +162,19 @@ public abstract class AbstractCompositionDefinition extends AbstractNonIdentifie
} }
else { else {
return new CompositeBasedBasicAttribute( return new CompositeBasedBasicAttribute(
AbstractCompositionDefinition.this, AbstractCompositionAttribute.this,
sessionFactory(), sessionFactory(),
subAttributeNumber, subAttributeNumber,
name, name,
type, type,
new BaselineAttributeInformation.Builder() new BaselineAttributeInformation.Builder()
.setInsertable( AbstractCompositionDefinition.this.isInsertable() ) .setInsertable( AbstractCompositionAttribute.this.isInsertable() )
.setUpdateable( AbstractCompositionDefinition.this.isUpdateable() ) .setUpdateable( AbstractCompositionAttribute.this.isUpdateable() )
.setInsertGenerated( AbstractCompositionDefinition.this.isInsertGenerated() ) .setInsertGenerated( AbstractCompositionAttribute.this.isInsertGenerated() )
.setUpdateGenerated( AbstractCompositionDefinition.this.isUpdateGenerated() ) .setUpdateGenerated( AbstractCompositionAttribute.this.isUpdateGenerated() )
.setNullable( getType().getPropertyNullability()[subAttributeNumber] ) .setNullable( getType().getPropertyNullability()[subAttributeNumber] )
.setDirtyCheckable( true ) .setDirtyCheckable( true )
.setVersionable( AbstractCompositionDefinition.this.isVersionable() ) .setVersionable( AbstractCompositionAttribute.this.isVersionable() )
.setCascadeStyle( getType().getCascadeStyle( subAttributeNumber ) ) .setCascadeStyle( getType().getCascadeStyle( subAttributeNumber ) )
.setFetchMode( getType().getFetchMode( subAttributeNumber ) ) .setFetchMode( getType().getFetchMode( subAttributeNumber ) )
.createInformation() .createInformation()
@ -196,7 +196,7 @@ public abstract class AbstractCompositionDefinition extends AbstractNonIdentifie
return ( (EntityDefinition) getSource() ).getEntityPersister(); return ( (EntityDefinition) getSource() ).getEntityPersister();
} }
else { else {
return ( (AbstractCompositionDefinition) getSource() ).locateOwningPersister(); return ( (AbstractCompositionAttribute) getSource() ).locateOwningPersister();
} }
} }

View File

@ -55,7 +55,7 @@ public class CompositeBasedAssociationAttribute
private Joinable joinable; private Joinable joinable;
public CompositeBasedAssociationAttribute( public CompositeBasedAssociationAttribute(
AbstractCompositionDefinition source, AbstractCompositionAttribute source,
SessionFactoryImplementor factory, SessionFactoryImplementor factory,
int attributeNumber, int attributeNumber,
String attributeName, String attributeName,

View File

@ -32,7 +32,7 @@ import org.hibernate.type.CompositeType;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class CompositionBasedCompositionAttribute public class CompositionBasedCompositionAttribute
extends AbstractCompositionDefinition extends AbstractCompositionAttribute
implements CompositionDefinition { implements CompositionDefinition {
public CompositionBasedCompositionAttribute( public CompositionBasedCompositionAttribute(
CompositionDefinition source, CompositionDefinition source,

View File

@ -25,7 +25,7 @@ package org.hibernate.tuple.entity;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.tuple.component.AbstractCompositionDefinition; import org.hibernate.tuple.component.AbstractCompositionAttribute;
import org.hibernate.persister.walking.spi.CompositionDefinition; import org.hibernate.persister.walking.spi.CompositionDefinition;
import org.hibernate.tuple.BaselineAttributeInformation; import org.hibernate.tuple.BaselineAttributeInformation;
import org.hibernate.type.CompositeType; import org.hibernate.type.CompositeType;
@ -34,7 +34,7 @@ import org.hibernate.type.CompositeType;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class EntityBasedCompositionAttribute public class EntityBasedCompositionAttribute
extends AbstractCompositionDefinition extends AbstractCompositionAttribute
implements CompositionDefinition { implements CompositionDefinition {
public EntityBasedCompositionAttribute( public EntityBasedCompositionAttribute(

View File

@ -42,6 +42,7 @@ import javax.persistence.EnumType;
import javax.persistence.Enumerated; import javax.persistence.Enumerated;
import javax.persistence.FetchType; import javax.persistence.FetchType;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.ManyToOne;
import org.junit.Test; import org.junit.Test;
@ -60,6 +61,7 @@ import org.hibernate.loader.spi.LoadQueryAliasResolutionContext;
import org.hibernate.loader.spi.NamedParameterContext; import org.hibernate.loader.spi.NamedParameterContext;
import org.hibernate.loader.spi.NoOpLoadPlanAdvisor; import org.hibernate.loader.spi.NoOpLoadPlanAdvisor;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.test.component.cascading.toone.PersonalInfo;
import org.hibernate.testing.FailureExpected; import org.hibernate.testing.FailureExpected;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.hibernate.testing.junit4.ExtraAssertions; import org.hibernate.testing.junit4.ExtraAssertions;
@ -128,12 +130,15 @@ public class EncapsulatedCompositeAttributeResultSetProcessorTest extends BaseCo
session.close(); session.close();
} }
/*
@Test @Test
public void testNestedCompositeElementCollectionProcessing() throws Exception { public void testNestedCompositeElementCollectionProcessing() throws Exception {
// create some test data // create some test data
Session session = openSession(); Session session = openSession();
session.beginTransaction(); session.beginTransaction();
Person person = new Person();
person.id = 1;
person.name = "Joe Blow";
session.save( person );
Customer customer = new Customer(); Customer customer = new Customer();
customer.id = 1L; customer.id = 1L;
Investment investment1 = new Investment(); Investment investment1 = new Investment();
@ -142,6 +147,7 @@ public class EncapsulatedCompositeAttributeResultSetProcessorTest extends BaseCo
investment1.monetaryAmount = new MonetaryAmount(); investment1.monetaryAmount = new MonetaryAmount();
investment1.monetaryAmount.currency = MonetaryAmount.CurrencyCode.USD; investment1.monetaryAmount.currency = MonetaryAmount.CurrencyCode.USD;
investment1.monetaryAmount.amount = BigDecimal.valueOf( 1234, 2 ); investment1.monetaryAmount.amount = BigDecimal.valueOf( 1234, 2 );
investment1.performedBy = person;
Investment investment2 = new Investment(); Investment investment2 = new Investment();
investment2.description = "bond"; investment2.description = "bond";
investment2.date = new Date(); investment2.date = new Date();
@ -173,11 +179,11 @@ public class EncapsulatedCompositeAttributeResultSetProcessorTest extends BaseCo
// clean up test data // clean up test data
session = openSession(); session = openSession();
session.beginTransaction(); session.beginTransaction();
session.createQuery( "delete Customer" ).executeUpdate(); session.delete( customerWork.investments.get( 0 ).performedBy );
session.delete( customerWork );
session.getTransaction().commit(); session.getTransaction().commit();
session.close(); session.close();
} }
*/
private List<?> getResults(EntityPersister entityPersister ) { private List<?> getResults(EntityPersister entityPersister ) {
final SingleRootReturnLoadPlanBuilderStrategy strategy = new SingleRootReturnLoadPlanBuilderStrategy( final SingleRootReturnLoadPlanBuilderStrategy strategy = new SingleRootReturnLoadPlanBuilderStrategy(
@ -288,6 +294,7 @@ public class EncapsulatedCompositeAttributeResultSetProcessorTest extends BaseCo
private MonetaryAmount monetaryAmount; private MonetaryAmount monetaryAmount;
private String description; private String description;
private Date date; private Date date;
private Person performedBy;
@Embedded @Embedded
public MonetaryAmount getMonetaryAmount() { public MonetaryAmount getMonetaryAmount() {
@ -308,6 +315,13 @@ public class EncapsulatedCompositeAttributeResultSetProcessorTest extends BaseCo
public void setDate(Date date) { public void setDate(Date date) {
this.date = date; this.date = date;
} }
@ManyToOne
public Person getPerformedBy() {
return performedBy;
}
public void setPerformedBy(Person performedBy) {
this.performedBy = performedBy;
}
} }
@Embeddable @Embeddable

View File

@ -38,6 +38,7 @@ import org.hibernate.persister.walking.spi.CollectionDefinition;
import org.hibernate.persister.walking.spi.CollectionElementDefinition; import org.hibernate.persister.walking.spi.CollectionElementDefinition;
import org.hibernate.persister.walking.spi.CollectionIndexDefinition; import org.hibernate.persister.walking.spi.CollectionIndexDefinition;
import org.hibernate.persister.walking.spi.CompositionDefinition; import org.hibernate.persister.walking.spi.CompositionDefinition;
import org.hibernate.persister.walking.spi.CompositionElementDefinition;
import org.hibernate.persister.walking.spi.EntityDefinition; import org.hibernate.persister.walking.spi.EntityDefinition;
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition; import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
import org.hibernate.persister.walking.spi.MetadataDrivenModelGraphVisitor; import org.hibernate.persister.walking.spi.MetadataDrivenModelGraphVisitor;
@ -168,6 +169,28 @@ public class BasicWalkingTest extends BaseCoreFunctionalTestCase {
); );
} }
@Override
public void startingCompositeElement(CompositionElementDefinition compositionElementDefinition) {
System.out.println(
String.format(
"%s Starting composite (%s)",
StringHelper.repeat( ">>", ++depth ),
compositionElementDefinition.toString()
)
);
}
@Override
public void finishingCompositeElement(CompositionElementDefinition compositionElementDefinition) {
System.out.println(
String.format(
"%s Finishing composite (%s)",
StringHelper.repeat( ">>", depth-- ),
compositionElementDefinition.toString()
)
);
}
@Override @Override
public boolean startingAttribute(AttributeDefinition attributeDefinition) { public boolean startingAttribute(AttributeDefinition attributeDefinition) {
System.out.println( System.out.println(