HHH-7841 - Redesign Loader
HHH-7841 - Redesign Loader HHH-7841 - Redesign Loader HHH-7841 - Redesign Loader
This commit is contained in:
parent
7bd9ba2adf
commit
043d618c03
|
@ -56,12 +56,11 @@ public abstract class AbstractJoinableAssociationImpl implements JoinableAssocia
|
|||
EntityReference currentEntityReference,
|
||||
CollectionReference currentCollectionReference,
|
||||
String withClause,
|
||||
boolean isNullable,
|
||||
boolean hasRestriction,
|
||||
Map<String, Filter> enabledFilters) throws MappingException {
|
||||
this.propertyPath = currentFetch.getPropertyPath();
|
||||
if ( currentFetch.getFetchStrategy().getStyle() == FetchStyle.JOIN ) {
|
||||
joinType = isNullable ? JoinType.LEFT_OUTER_JOIN : JoinType.INNER_JOIN;
|
||||
joinType = currentFetch.isNullable() ? JoinType.LEFT_OUTER_JOIN : JoinType.INNER_JOIN;
|
||||
}
|
||||
else {
|
||||
joinType = JoinType.NONE;
|
||||
|
|
|
@ -56,7 +56,6 @@ public class CollectionJoinableAssociationImpl extends AbstractJoinableAssociati
|
|||
currentEntityReference,
|
||||
collectionFetch,
|
||||
withClause,
|
||||
true,
|
||||
hasRestriction,
|
||||
enabledFilters
|
||||
);
|
||||
|
|
|
@ -48,7 +48,6 @@ public class EntityJoinableAssociationImpl extends AbstractJoinableAssociationIm
|
|||
EntityFetch entityFetch,
|
||||
CollectionReference currentCollectionReference,
|
||||
String withClause,
|
||||
boolean isNullable,
|
||||
boolean hasRestriction,
|
||||
Map<String, Filter> enabledFilters) throws MappingException {
|
||||
super(
|
||||
|
@ -56,7 +55,6 @@ public class EntityJoinableAssociationImpl extends AbstractJoinableAssociationIm
|
|||
entityFetch,
|
||||
currentCollectionReference,
|
||||
withClause,
|
||||
isNullable,
|
||||
hasRestriction,
|
||||
enabledFilters
|
||||
);
|
||||
|
|
|
@ -149,14 +149,10 @@ public class EntityLoadQueryBuilderImpl implements LoadQueryBuilder {
|
|||
|
||||
@Override
|
||||
public void startingEntityFetch(EntityFetch entityFetch) {
|
||||
final OuterJoinLoadable ownerPersister = (OuterJoinLoadable) entityFetch.getOwner().retrieveFetchSourcePersister();
|
||||
final int propertyNumber = ownerPersister.getEntityMetamodel().getPropertyIndex( entityFetch.getOwnerPropertyName() );
|
||||
final boolean isNullable = ownerPersister.isSubclassPropertyNullable( propertyNumber );
|
||||
EntityJoinableAssociationImpl assoc = new EntityJoinableAssociationImpl(
|
||||
entityFetch,
|
||||
getCurrentCollectionReference(),
|
||||
"", // getWithClause( entityFetch.getPropertyPath() )
|
||||
isNullable,
|
||||
false, // hasRestriction( entityFetch.getPropertyPath() )
|
||||
loadQueryInfluencers.getEnabledFilters()
|
||||
);
|
||||
|
|
|
@ -27,7 +27,6 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
|
||||
import org.hibernate.cfg.NotYetImplementedException;
|
||||
import org.hibernate.engine.internal.JoinHelper;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.loader.CollectionAliases;
|
||||
|
@ -36,6 +35,8 @@ import org.hibernate.loader.EntityAliases;
|
|||
import org.hibernate.loader.GeneratedCollectionAliases;
|
||||
import org.hibernate.loader.plan.spi.CollectionReference;
|
||||
import org.hibernate.loader.plan.spi.CollectionReturn;
|
||||
import org.hibernate.loader.plan.spi.CompositeElementGraph;
|
||||
import org.hibernate.loader.plan.spi.CompositeIndexGraph;
|
||||
import org.hibernate.loader.plan.spi.EntityReference;
|
||||
import org.hibernate.loader.plan.spi.EntityReturn;
|
||||
import org.hibernate.loader.plan.spi.Fetch;
|
||||
|
@ -46,7 +47,6 @@ import org.hibernate.loader.spi.LoadQueryAliasResolutionContext;
|
|||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.Loadable;
|
||||
import org.hibernate.persister.entity.OuterJoinLoadable;
|
||||
import org.hibernate.type.EntityType;
|
||||
|
||||
/**
|
||||
|
@ -214,9 +214,18 @@ public class LoadQueryAliasResolutionContextImpl implements LoadQueryAliasResolu
|
|||
if ( EntityReference.class.isInstance( currentFetch.getOwner() ) ) {
|
||||
lhsAlias = resolveEntityTableAlias( (EntityReference) currentFetch.getOwner() );
|
||||
}
|
||||
else {
|
||||
throw new NotYetImplementedException( "Cannot determine LHS alias for a FetchOwner that is not an EntityReference yet." );
|
||||
else if ( CompositeElementGraph.class.isInstance( currentFetch.getOwner() ) ) {
|
||||
CompositeElementGraph compositeElementGraph = (CompositeElementGraph) currentFetch.getOwner();
|
||||
lhsAlias = resolveCollectionTableAlias( compositeElementGraph.getCollectionReference() );
|
||||
}
|
||||
else if ( CompositeIndexGraph.class.isInstance( currentFetch.getOwner() ) ) {
|
||||
CompositeIndexGraph compositeIndexGraph = (CompositeIndexGraph) currentFetch.getOwner();
|
||||
lhsAlias = resolveCollectionTableAlias( compositeIndexGraph.getCollectionReference() );
|
||||
}
|
||||
else {
|
||||
throw new NotYetImplementedException( "Cannot determine LHS alias for FetchOwner." );
|
||||
}
|
||||
final String[] aliasedLhsColumnNames = StringHelper.qualify( lhsAlias, currentFetch.getColumnNames() );
|
||||
final String rhsAlias;
|
||||
if ( EntityReference.class.isInstance( currentFetch ) ) {
|
||||
rhsAlias = resolveEntityTableAlias( (EntityReference) currentFetch );
|
||||
|
@ -229,15 +238,6 @@ public class LoadQueryAliasResolutionContextImpl implements LoadQueryAliasResolu
|
|||
}
|
||||
|
||||
// TODO: can't this be found in CollectionAliases or EntityAliases? should be moved to LoadQueryAliasResolutionContextImpl
|
||||
final OuterJoinLoadable fetchSourcePersister = (OuterJoinLoadable) currentFetch.getOwner().retrieveFetchSourcePersister();
|
||||
final int propertyNumber = fetchSourcePersister.getEntityMetamodel().getPropertyIndex( currentFetch.getOwnerPropertyName() );
|
||||
final String[] aliasedLhsColumnNames = JoinHelper.getAliasedLHSColumnNames(
|
||||
joinableAssociation.getAssociationType(),
|
||||
lhsAlias,
|
||||
propertyNumber,
|
||||
fetchSourcePersister,
|
||||
sessionFactory
|
||||
);
|
||||
|
||||
aliases = new JoinableAssociationAliasesImpl( lhsAlias, aliasedLhsColumnNames, rhsAlias );
|
||||
aliasesByJoinableAssociation.put( joinableAssociation, aliases );
|
||||
|
|
|
@ -27,20 +27,24 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
|
||||
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public abstract class AbstractFetchOwner extends AbstractPlanNode implements FetchOwner {
|
||||
private final LockMode lockMode;
|
||||
|
||||
private List<Fetch> fetches;
|
||||
|
||||
public AbstractFetchOwner(SessionFactoryImplementor factory, LockMode lockMode) {
|
||||
public AbstractFetchOwner(SessionFactoryImplementor factory) {
|
||||
super( factory );
|
||||
this.lockMode = lockMode;
|
||||
validate();
|
||||
}
|
||||
|
||||
|
@ -50,11 +54,10 @@ public abstract class AbstractFetchOwner extends AbstractPlanNode implements Fet
|
|||
/**
|
||||
* A "copy" constructor. Used while making clones/copies of this.
|
||||
*
|
||||
* @param original
|
||||
* @param original - the original object to copy.
|
||||
*/
|
||||
protected AbstractFetchOwner(AbstractFetchOwner original, CopyContext copyContext) {
|
||||
super( original );
|
||||
this.lockMode = original.lockMode;
|
||||
validate();
|
||||
|
||||
copyContext.getReturnGraphVisitationStrategy().startingFetches( original );
|
||||
|
@ -62,6 +65,7 @@ public abstract class AbstractFetchOwner extends AbstractPlanNode implements Fet
|
|||
this.fetches = Collections.emptyList();
|
||||
}
|
||||
else {
|
||||
// TODO: don't think this is correct...
|
||||
List<Fetch> fetchesCopy = new ArrayList<Fetch>();
|
||||
for ( Fetch fetch : fetches ) {
|
||||
fetchesCopy.add( fetch.makeCopy( copyContext, this ) );
|
||||
|
@ -71,11 +75,6 @@ public abstract class AbstractFetchOwner extends AbstractPlanNode implements Fet
|
|||
copyContext.getReturnGraphVisitationStrategy().finishingFetches( original );
|
||||
}
|
||||
|
||||
public LockMode getLockMode() {
|
||||
return lockMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFetch(Fetch fetch) {
|
||||
if ( fetch.getOwner() != this ) {
|
||||
throw new IllegalArgumentException( "Fetch and owner did not match" );
|
||||
|
@ -92,4 +91,55 @@ public abstract class AbstractFetchOwner extends AbstractPlanNode implements Fet
|
|||
public Fetch[] getFetches() {
|
||||
return fetches == null ? NO_FETCHES : fetches.toArray( new Fetch[ fetches.size() ] );
|
||||
}
|
||||
|
||||
protected abstract FetchOwnerDelegate getFetchOwnerDelegate();
|
||||
|
||||
@Override
|
||||
public boolean isNullable(Fetch fetch) {
|
||||
return getFetchOwnerDelegate().isNullable( fetch );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType(Fetch fetch) {
|
||||
return getFetchOwnerDelegate().getType( fetch );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getColumnNames(Fetch fetch) {
|
||||
return getFetchOwnerDelegate().getColumnNames( fetch );
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionFetch buildCollectionFetch(
|
||||
AssociationAttributeDefinition attributeDefinition,
|
||||
FetchStrategy fetchStrategy,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardCollectionFetch(
|
||||
this,
|
||||
attributeDefinition,
|
||||
fetchStrategy,
|
||||
loadPlanBuildingContext
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityFetch buildEntityFetch(
|
||||
AssociationAttributeDefinition attributeDefinition,
|
||||
FetchStrategy fetchStrategy,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardEntityFetch(
|
||||
this,
|
||||
attributeDefinition,
|
||||
fetchStrategy,
|
||||
loadPlanBuildingContext
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompositeFetch buildCompositeFetch(
|
||||
CompositionDefinition attributeDefinition,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
package org.hibernate.loader.plan.spi;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.FetchStyle;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
@ -42,11 +41,10 @@ public abstract class AbstractSingularAttributeFetch extends AbstractFetchOwner
|
|||
|
||||
public AbstractSingularAttributeFetch(
|
||||
SessionFactoryImplementor factory,
|
||||
LockMode lockMode,
|
||||
FetchOwner owner,
|
||||
String ownerProperty,
|
||||
FetchStrategy fetchStrategy) {
|
||||
super( factory, lockMode );
|
||||
super( factory );
|
||||
this.owner = owner;
|
||||
this.ownerProperty = ownerProperty;
|
||||
this.fetchStrategy = fetchStrategy;
|
||||
|
@ -77,6 +75,16 @@ public abstract class AbstractSingularAttributeFetch extends AbstractFetchOwner
|
|||
return ownerProperty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNullable() {
|
||||
return owner.isNullable( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getColumnNames() {
|
||||
return owner.getColumnNames( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchStrategy getFetchStrategy() {
|
||||
return fetchStrategy;
|
||||
|
|
|
@ -28,8 +28,10 @@ import java.sql.SQLException;
|
|||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.internal.JoinHelper;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.loader.spi.ResultSetProcessingContext;
|
||||
import org.hibernate.persister.entity.Joinable;
|
||||
import org.hibernate.type.CollectionType;
|
||||
|
||||
/**
|
||||
|
@ -74,6 +76,16 @@ public class CollectionFetch extends AbstractCollectionReference implements Fetc
|
|||
return getPropertyPath().getProperty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNullable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getColumnNames() {
|
||||
return getOwner().getColumnNames( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchStrategy getFetchStrategy() {
|
||||
return fetchStrategy;
|
||||
|
|
|
@ -1,29 +1,24 @@
|
|||
package org.hibernate.loader.plan.spi;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.loader.PropertyPath;
|
||||
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
|
||||
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.collection.QueryableCollection;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||
import org.hibernate.type.CompositeType;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class CompositeElementGraph extends AbstractPlanNode implements FetchableCollectionElement {
|
||||
public class CompositeElementGraph extends AbstractFetchOwner implements FetchableCollectionElement {
|
||||
private final CollectionReference collectionReference;
|
||||
private final PropertyPath propertyPath;
|
||||
private final CollectionPersister collectionPersister;
|
||||
|
||||
private List<Fetch> fetches;
|
||||
private final FetchOwnerDelegate fetchOwnerDelegate;
|
||||
|
||||
public CompositeElementGraph(
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
|
@ -34,39 +29,24 @@ public class CompositeElementGraph extends AbstractPlanNode implements Fetchable
|
|||
this.collectionReference = collectionReference;
|
||||
this.collectionPersister = collectionReference.getCollectionPersister();
|
||||
this.propertyPath = collectionPath.append( "<elements>" );
|
||||
this.fetchOwnerDelegate = new CompositeFetchOwnerDelegate(
|
||||
sessionFactory,
|
||||
(CompositeType) collectionPersister.getElementType(),
|
||||
( (QueryableCollection) collectionPersister ).getElementColumnNames()
|
||||
);
|
||||
}
|
||||
|
||||
public CompositeElementGraph(CompositeElementGraph original, CopyContext copyContext) {
|
||||
super( original );
|
||||
super( original, copyContext );
|
||||
this.collectionReference = original.collectionReference;
|
||||
this.collectionPersister = original.collectionPersister;
|
||||
this.propertyPath = original.propertyPath;
|
||||
|
||||
copyContext.getReturnGraphVisitationStrategy().startingFetches( original );
|
||||
if ( fetches == null || fetches.size() == 0 ) {
|
||||
this.fetches = Collections.emptyList();
|
||||
}
|
||||
else {
|
||||
List<Fetch> fetchesCopy = new ArrayList<Fetch>();
|
||||
for ( Fetch fetch : fetches ) {
|
||||
fetchesCopy.add( fetch.makeCopy( copyContext, this ) );
|
||||
}
|
||||
this.fetches = fetchesCopy;
|
||||
}
|
||||
copyContext.getReturnGraphVisitationStrategy().finishingFetches( original );
|
||||
this.fetchOwnerDelegate = original.fetchOwnerDelegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFetch(Fetch fetch) {
|
||||
if ( fetches == null ) {
|
||||
fetches = new ArrayList<Fetch>();
|
||||
}
|
||||
fetches.add( fetch );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fetch[] getFetches() {
|
||||
return fetches == null ? NO_FETCHES : fetches.toArray( new Fetch[ fetches.size() ] );
|
||||
public CollectionReference getCollectionReference() {
|
||||
return collectionReference;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -83,6 +63,16 @@ public class CompositeElementGraph extends AbstractPlanNode implements Fetchable
|
|||
return propertyPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompositeElementGraph makeCopy(CopyContext copyContext) {
|
||||
return new CompositeElementGraph( this, copyContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FetchOwnerDelegate getFetchOwnerDelegate() {
|
||||
return fetchOwnerDelegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionFetch buildCollectionFetch(
|
||||
AssociationAttributeDefinition attributeDefinition,
|
||||
|
@ -90,29 +80,4 @@ public class CompositeElementGraph extends AbstractPlanNode implements Fetchable
|
|||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
throw new HibernateException( "Collection composite element cannot define collections" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityFetch buildEntityFetch(
|
||||
AssociationAttributeDefinition attributeDefinition,
|
||||
FetchStrategy fetchStrategy,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardEntityFetch(
|
||||
this,
|
||||
attributeDefinition,
|
||||
fetchStrategy,
|
||||
loadPlanBuildingContext
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompositeFetch buildCompositeFetch(
|
||||
CompositionDefinition attributeDefinition,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompositeElementGraph makeCopy(CopyContext copyContext) {
|
||||
return new CompositeElementGraph( this, copyContext );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,8 +25,6 @@ package org.hibernate.loader.plan.spi;
|
|||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.FetchStyle;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
|
@ -37,6 +35,7 @@ import org.hibernate.loader.spi.ResultSetProcessingContext;
|
|||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||
import org.hibernate.type.CompositeType;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
|
@ -44,15 +43,28 @@ import org.hibernate.persister.walking.spi.CompositionDefinition;
|
|||
public class CompositeFetch extends AbstractSingularAttributeFetch {
|
||||
public static final FetchStrategy FETCH_PLAN = new FetchStrategy( FetchTiming.IMMEDIATE, FetchStyle.JOIN );
|
||||
|
||||
private final FetchOwnerDelegate delegate;
|
||||
|
||||
public CompositeFetch(
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
FetchOwner owner,
|
||||
String ownerProperty) {
|
||||
super( sessionFactory, LockMode.NONE, owner, ownerProperty, FETCH_PLAN );
|
||||
super( sessionFactory, owner, ownerProperty, FETCH_PLAN );
|
||||
this.delegate = new CompositeFetchOwnerDelegate(
|
||||
sessionFactory,
|
||||
(CompositeType) getOwner().getType( this ),
|
||||
getOwner().getColumnNames( this )
|
||||
);
|
||||
}
|
||||
|
||||
public CompositeFetch(CompositeFetch original, CopyContext copyContext, FetchOwner fetchOwnerCopy) {
|
||||
super( original, copyContext, fetchOwnerCopy );
|
||||
this.delegate = original.getFetchOwnerDelegate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FetchOwnerDelegate getFetchOwnerDelegate() {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -1,29 +1,24 @@
|
|||
package org.hibernate.loader.plan.spi;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.loader.PropertyPath;
|
||||
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
|
||||
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.collection.QueryableCollection;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||
import org.hibernate.type.CompositeType;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class CompositeIndexGraph extends AbstractPlanNode implements FetchableCollectionIndex {
|
||||
public class CompositeIndexGraph extends AbstractFetchOwner implements FetchableCollectionIndex {
|
||||
private final CollectionReference collectionReference;
|
||||
private final PropertyPath propertyPath;
|
||||
private final CollectionPersister collectionPersister;
|
||||
|
||||
private List<Fetch> fetches;
|
||||
private final FetchOwnerDelegate fetchOwnerDelegate;
|
||||
|
||||
public CompositeIndexGraph(
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
|
@ -33,39 +28,19 @@ public class CompositeIndexGraph extends AbstractPlanNode implements FetchableCo
|
|||
this.collectionReference = collectionReference;
|
||||
this.collectionPersister = collectionReference.getCollectionPersister();
|
||||
this.propertyPath = propertyPath.append( "<index>" );
|
||||
this.fetchOwnerDelegate = new CompositeFetchOwnerDelegate(
|
||||
sessionFactory,
|
||||
(CompositeType) collectionPersister.getIndexType(),
|
||||
( (QueryableCollection) collectionPersister ).getIndexColumnNames()
|
||||
);
|
||||
}
|
||||
|
||||
protected CompositeIndexGraph(CompositeIndexGraph original, CopyContext copyContext) {
|
||||
super( original );
|
||||
super( original, copyContext );
|
||||
this.collectionReference = original.collectionReference;
|
||||
this.collectionPersister = original.collectionPersister;
|
||||
this.propertyPath = original.propertyPath;
|
||||
|
||||
copyContext.getReturnGraphVisitationStrategy().startingFetches( original );
|
||||
if ( fetches == null || fetches.size() == 0 ) {
|
||||
this.fetches = Collections.emptyList();
|
||||
}
|
||||
else {
|
||||
List<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() ] );
|
||||
this.fetchOwnerDelegate = original.fetchOwnerDelegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -77,12 +52,25 @@ public class CompositeIndexGraph extends AbstractPlanNode implements FetchableCo
|
|||
return collectionPersister.getOwnerEntityPersister();
|
||||
}
|
||||
|
||||
public CollectionReference getCollectionReference() {
|
||||
return collectionReference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyPath getPropertyPath() {
|
||||
return propertyPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompositeIndexGraph makeCopy(CopyContext copyContext) {
|
||||
return new CompositeIndexGraph( this, copyContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FetchOwnerDelegate getFetchOwnerDelegate() {
|
||||
return fetchOwnerDelegate;
|
||||
}
|
||||
|
||||
public CollectionFetch buildCollectionFetch(
|
||||
AssociationAttributeDefinition attributeDefinition,
|
||||
FetchStrategy fetchStrategy,
|
||||
|
@ -90,28 +78,4 @@ public class CompositeIndexGraph extends AbstractPlanNode implements FetchableCo
|
|||
throw new HibernateException( "Composite index cannot define collections" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityFetch buildEntityFetch(
|
||||
AssociationAttributeDefinition attributeDefinition,
|
||||
FetchStrategy fetchStrategy,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardEntityFetch(
|
||||
this,
|
||||
attributeDefinition,
|
||||
fetchStrategy,
|
||||
loadPlanBuildingContext
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompositeFetch buildCompositeFetch(
|
||||
CompositionDefinition attributeDefinition,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompositeIndexGraph makeCopy(CopyContext copyContext) {
|
||||
return new CompositeIndexGraph( this, copyContext );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,32 +1,23 @@
|
|||
package org.hibernate.loader.plan.spi;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.loader.PropertyPath;
|
||||
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
|
||||
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||
import org.hibernate.type.AssociationType;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class EntityElementGraph extends AbstractPlanNode implements FetchableCollectionElement, EntityReference {
|
||||
public class EntityElementGraph extends AbstractFetchOwner implements FetchableCollectionElement, EntityReference {
|
||||
private final CollectionReference collectionReference;
|
||||
private final CollectionPersister collectionPersister;
|
||||
private final AssociationType elementType;
|
||||
private final EntityPersister elementPersister;
|
||||
private final PropertyPath propertyPath;
|
||||
|
||||
private List<Fetch> fetches;
|
||||
private final FetchOwnerDelegate fetchOwnerDelegate;
|
||||
|
||||
private IdentifierDescription identifierDescription;
|
||||
|
||||
|
@ -40,30 +31,19 @@ public class EntityElementGraph extends AbstractPlanNode implements FetchableCol
|
|||
this.collectionPersister = collectionReference.getCollectionPersister();
|
||||
this.elementType = (AssociationType) collectionPersister.getElementType();
|
||||
this.elementPersister = (EntityPersister) this.elementType.getAssociatedJoinable( sessionFactory() );
|
||||
this.propertyPath = collectionPath.append( "<elements>" );
|
||||
this.propertyPath = collectionPath;
|
||||
this.fetchOwnerDelegate = new EntityFetchOwnerDelegate( elementPersister );
|
||||
}
|
||||
|
||||
public EntityElementGraph(EntityElementGraph original, CopyContext copyContext) {
|
||||
super( original );
|
||||
super( original, copyContext );
|
||||
|
||||
this.collectionReference = original.collectionReference;
|
||||
this.collectionPersister = original.collectionReference.getCollectionPersister();
|
||||
this.elementType = original.elementType;
|
||||
this.elementPersister = original.elementPersister;
|
||||
this.propertyPath = original.propertyPath;
|
||||
|
||||
copyContext.getReturnGraphVisitationStrategy().startingFetches( original );
|
||||
if ( fetches == null || fetches.size() == 0 ) {
|
||||
this.fetches = Collections.emptyList();
|
||||
}
|
||||
else {
|
||||
List<Fetch> fetchesCopy = new ArrayList<Fetch>();
|
||||
for ( Fetch fetch : fetches ) {
|
||||
fetchesCopy.add( fetch.makeCopy( copyContext, this ) );
|
||||
}
|
||||
this.fetches = fetchesCopy;
|
||||
}
|
||||
copyContext.getReturnGraphVisitationStrategy().finishingFetches( original );
|
||||
this.fetchOwnerDelegate = original.fetchOwnerDelegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -86,19 +66,6 @@ public class EntityElementGraph extends AbstractPlanNode implements FetchableCol
|
|||
return identifierDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFetch(Fetch fetch) {
|
||||
if ( fetches == null ) {
|
||||
fetches = new ArrayList<Fetch>();
|
||||
}
|
||||
fetches.add( fetch );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fetch[] getFetches() {
|
||||
return fetches == null ? NO_FETCHES : fetches.toArray( new Fetch[ fetches.size() ] );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateFetchPlan(FetchStrategy fetchStrategy) {
|
||||
}
|
||||
|
@ -113,39 +80,6 @@ public class EntityElementGraph extends AbstractPlanNode implements FetchableCol
|
|||
return propertyPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionFetch buildCollectionFetch(
|
||||
AssociationAttributeDefinition attributeDefinition,
|
||||
FetchStrategy fetchStrategy,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardCollectionFetch(
|
||||
this,
|
||||
attributeDefinition,
|
||||
fetchStrategy,
|
||||
loadPlanBuildingContext
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityFetch buildEntityFetch(
|
||||
AssociationAttributeDefinition attributeDefinition,
|
||||
FetchStrategy fetchStrategy,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardEntityFetch(
|
||||
this,
|
||||
attributeDefinition,
|
||||
fetchStrategy,
|
||||
loadPlanBuildingContext
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompositeFetch buildCompositeFetch(
|
||||
CompositionDefinition attributeDefinition,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectIdentifierDescription(IdentifierDescription identifierDescription) {
|
||||
this.identifierDescription = identifierDescription;
|
||||
|
@ -156,8 +90,18 @@ public class EntityElementGraph extends AbstractPlanNode implements FetchableCol
|
|||
return new EntityElementGraph( this, copyContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionReference getCollectionReference() {
|
||||
return collectionReference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EntityElementGraph(collection=" + collectionPersister.getRole() + ", type=" + elementPersister.getEntityName() + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FetchOwnerDelegate getFetchOwnerDelegate() {
|
||||
return fetchOwnerDelegate;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,21 +32,19 @@ import org.hibernate.engine.FetchStrategy;
|
|||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.engine.spi.EntityKey;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
|
||||
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
||||
import org.hibernate.loader.spi.ResultSetProcessingContext;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||
import org.hibernate.type.EntityType;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class EntityFetch extends AbstractSingularAttributeFetch implements EntityReference {
|
||||
public class EntityFetch extends AbstractSingularAttributeFetch implements EntityReference, Fetch {
|
||||
|
||||
private final EntityType associationType;
|
||||
private final EntityPersister persister;
|
||||
private final LockMode lockMode;
|
||||
private final FetchOwnerDelegate fetchOwnerDelegate;
|
||||
|
||||
private IdentifierDescription identifierDescription;
|
||||
|
||||
|
@ -57,10 +55,12 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit
|
|||
String ownerProperty,
|
||||
EntityType entityType,
|
||||
FetchStrategy fetchStrategy) {
|
||||
super( sessionFactory, lockMode, owner, ownerProperty, fetchStrategy );
|
||||
super( sessionFactory, owner, ownerProperty, fetchStrategy );
|
||||
|
||||
this.associationType = entityType;
|
||||
this.persister = sessionFactory.getEntityPersister( associationType.getAssociatedEntityName() );
|
||||
this.lockMode = lockMode;
|
||||
this.fetchOwnerDelegate = new EntityFetchOwnerDelegate( persister );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -73,6 +73,8 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit
|
|||
super( original, copyContext, fetchOwnerCopy );
|
||||
this.associationType = original.associationType;
|
||||
this.persister = original.persister;
|
||||
this.lockMode = original.lockMode;
|
||||
this.fetchOwnerDelegate = original.fetchOwnerDelegate;
|
||||
}
|
||||
|
||||
public EntityType getAssociationType() {
|
||||
|
@ -94,45 +96,16 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit
|
|||
return identifierDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LockMode getLockMode() {
|
||||
return lockMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityPersister retrieveFetchSourcePersister() {
|
||||
return persister;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public CollectionFetch buildCollectionFetch(
|
||||
AssociationAttributeDefinition attributeDefinition,
|
||||
FetchStrategy fetchStrategy,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardCollectionFetch(
|
||||
this,
|
||||
attributeDefinition,
|
||||
fetchStrategy,
|
||||
loadPlanBuildingContext
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityFetch buildEntityFetch(
|
||||
AssociationAttributeDefinition attributeDefinition,
|
||||
FetchStrategy fetchStrategy,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardEntityFetch(
|
||||
this,
|
||||
attributeDefinition,
|
||||
fetchStrategy,
|
||||
loadPlanBuildingContext
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompositeFetch buildCompositeFetch(
|
||||
CompositionDefinition attributeDefinition,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectIdentifierDescription(IdentifierDescription identifierDescription) {
|
||||
this.identifierDescription = identifierDescription;
|
||||
|
@ -268,4 +241,9 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit
|
|||
copyContext.getReturnGraphVisitationStrategy().finishingEntityFetch( this );
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FetchOwnerDelegate getFetchOwnerDelegate() {
|
||||
return fetchOwnerDelegate;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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() );
|
||||
}
|
||||
}
|
|
@ -23,33 +23,24 @@
|
|||
*/
|
||||
package org.hibernate.loader.plan.spi;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.loader.PropertyPath;
|
||||
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
|
||||
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||
import org.hibernate.type.AssociationType;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class EntityIndexGraph extends AbstractPlanNode implements FetchableCollectionIndex, EntityReference {
|
||||
public class EntityIndexGraph extends AbstractFetchOwner implements FetchableCollectionIndex, EntityReference {
|
||||
private final CollectionReference collectionReference;
|
||||
private final CollectionPersister collectionPersister;
|
||||
private final AssociationType indexType;
|
||||
private final EntityPersister indexPersister;
|
||||
private final PropertyPath propertyPath;
|
||||
|
||||
private List<Fetch> fetches;
|
||||
private final FetchOwnerDelegate fetchOwnerDelegate;
|
||||
|
||||
private IdentifierDescription identifierDescription;
|
||||
|
||||
|
@ -63,28 +54,17 @@ public class EntityIndexGraph extends AbstractPlanNode implements FetchableColle
|
|||
this.indexType = (AssociationType) collectionPersister.getIndexType();
|
||||
this.indexPersister = (EntityPersister) this.indexType.getAssociatedJoinable( sessionFactory() );
|
||||
this.propertyPath = collectionPath.append( "<index>" ); // todo : do we want the <index> part?
|
||||
this.fetchOwnerDelegate = new EntityFetchOwnerDelegate( indexPersister );
|
||||
}
|
||||
|
||||
public EntityIndexGraph(EntityIndexGraph original, CopyContext copyContext) {
|
||||
super( original );
|
||||
super( original, copyContext );
|
||||
this.collectionReference = original.collectionReference;
|
||||
this.collectionPersister = original.collectionReference.getCollectionPersister();
|
||||
this.indexType = original.indexType;
|
||||
this.indexPersister = original.indexPersister;
|
||||
this.propertyPath = original.propertyPath;
|
||||
|
||||
copyContext.getReturnGraphVisitationStrategy().startingFetches( original );
|
||||
if ( fetches == null || fetches.size() == 0 ) {
|
||||
this.fetches = Collections.emptyList();
|
||||
}
|
||||
else {
|
||||
List<Fetch> fetchesCopy = new ArrayList<Fetch>();
|
||||
for ( Fetch fetch : fetches ) {
|
||||
fetchesCopy.add( fetch.makeCopy( copyContext, this ) );
|
||||
}
|
||||
this.fetches = fetchesCopy;
|
||||
}
|
||||
copyContext.getReturnGraphVisitationStrategy().finishingFetches( original );
|
||||
this.fetchOwnerDelegate = original.fetchOwnerDelegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -107,19 +87,6 @@ public class EntityIndexGraph extends AbstractPlanNode implements FetchableColle
|
|||
return identifierDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFetch(Fetch fetch) {
|
||||
if ( fetches == null ) {
|
||||
fetches = new ArrayList<Fetch>();
|
||||
}
|
||||
fetches.add( fetch );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fetch[] getFetches() {
|
||||
return fetches == null ? NO_FETCHES : fetches.toArray( new Fetch[ fetches.size() ] );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateFetchPlan(FetchStrategy fetchStrategy) {
|
||||
}
|
||||
|
@ -134,39 +101,6 @@ public class EntityIndexGraph extends AbstractPlanNode implements FetchableColle
|
|||
return propertyPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionFetch buildCollectionFetch(
|
||||
AssociationAttributeDefinition attributeDefinition,
|
||||
FetchStrategy fetchStrategy,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardCollectionFetch(
|
||||
this,
|
||||
attributeDefinition,
|
||||
fetchStrategy,
|
||||
loadPlanBuildingContext
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityFetch buildEntityFetch(
|
||||
AssociationAttributeDefinition attributeDefinition,
|
||||
FetchStrategy fetchStrategy,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardEntityFetch(
|
||||
this,
|
||||
attributeDefinition,
|
||||
fetchStrategy,
|
||||
loadPlanBuildingContext
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompositeFetch buildCompositeFetch(
|
||||
CompositionDefinition attributeDefinition,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectIdentifierDescription(IdentifierDescription identifierDescription) {
|
||||
this.identifierDescription = identifierDescription;
|
||||
|
@ -176,4 +110,9 @@ public class EntityIndexGraph extends AbstractPlanNode implements FetchableColle
|
|||
public EntityIndexGraph makeCopy(CopyContext copyContext) {
|
||||
return new EntityIndexGraph( this, copyContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FetchOwnerDelegate getFetchOwnerDelegate() {
|
||||
return fetchOwnerDelegate;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,12 +32,8 @@ import org.hibernate.engine.FetchStrategy;
|
|||
import org.hibernate.engine.spi.EntityKey;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.loader.PropertyPath;
|
||||
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
|
||||
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
||||
import org.hibernate.loader.spi.ResultSetProcessingContext;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||
|
||||
import static org.hibernate.loader.spi.ResultSetProcessingContext.IdentifierResolutionContext;
|
||||
|
||||
|
@ -50,24 +46,32 @@ public class EntityReturn extends AbstractFetchOwner implements Return, EntityRe
|
|||
|
||||
private final PropertyPath propertyPath = new PropertyPath(); // its a root
|
||||
|
||||
private final LockMode lockMode;
|
||||
|
||||
private final FetchOwnerDelegate fetchOwnerDelegate;
|
||||
|
||||
private IdentifierDescription identifierDescription;
|
||||
|
||||
public EntityReturn(
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
LockMode lockMode,
|
||||
String entityName) {
|
||||
super( sessionFactory, lockMode );
|
||||
|
||||
super( sessionFactory );
|
||||
this.persister = sessionFactory.getEntityPersister( entityName );
|
||||
this.lockMode = lockMode;
|
||||
this.fetchOwnerDelegate = new EntityFetchOwnerDelegate( persister );
|
||||
}
|
||||
|
||||
protected EntityReturn(EntityReturn original, CopyContext copyContext) {
|
||||
super( original, copyContext );
|
||||
this.persister = original.persister;
|
||||
this.lockMode = original.lockMode;
|
||||
this.fetchOwnerDelegate = original.fetchOwnerDelegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LockMode getLockMode() {
|
||||
return super.getLockMode();
|
||||
return lockMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -99,39 +103,6 @@ public class EntityReturn extends AbstractFetchOwner implements Return, EntityRe
|
|||
return propertyPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionFetch buildCollectionFetch(
|
||||
AssociationAttributeDefinition attributeDefinition,
|
||||
FetchStrategy fetchStrategy,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardCollectionFetch(
|
||||
this,
|
||||
attributeDefinition,
|
||||
fetchStrategy,
|
||||
loadPlanBuildingContext
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityFetch buildEntityFetch(
|
||||
AssociationAttributeDefinition attributeDefinition,
|
||||
FetchStrategy fetchStrategy,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardEntityFetch(
|
||||
this,
|
||||
attributeDefinition,
|
||||
fetchStrategy,
|
||||
loadPlanBuildingContext
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompositeFetch buildCompositeFetch(
|
||||
CompositionDefinition attributeDefinition,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hydrate(ResultSet resultSet, ResultSetProcessingContext context) throws SQLException {
|
||||
EntityKey entityKey = getEntityKeyFromContext( context );
|
||||
|
@ -207,4 +178,9 @@ public class EntityReturn extends AbstractFetchOwner implements Return, EntityRe
|
|||
public EntityReturn makeCopy(CopyContext copyContext) {
|
||||
return new EntityReturn( this, copyContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FetchOwnerDelegate getFetchOwnerDelegate() {
|
||||
return fetchOwnerDelegate;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,6 +52,10 @@ public interface Fetch extends CopyableFetch {
|
|||
*/
|
||||
public String getOwnerPropertyName();
|
||||
|
||||
public boolean isNullable();
|
||||
|
||||
public String[] getColumnNames();
|
||||
|
||||
public FetchStrategy getFetchStrategy();
|
||||
|
||||
/**
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
|||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* Contract for owners of fetches. Any non-scalar return could be a fetch owner.
|
||||
|
@ -56,6 +57,12 @@ public interface FetchOwner {
|
|||
*/
|
||||
public Fetch[] getFetches();
|
||||
|
||||
public Type getType(Fetch fetch);
|
||||
|
||||
public boolean isNullable(Fetch fetch);
|
||||
|
||||
public String[] getColumnNames(Fetch fetch);
|
||||
|
||||
/**
|
||||
* Is the asserted plan valid from this owner to a fetch?
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -23,10 +23,14 @@
|
|||
*/
|
||||
package org.hibernate.loader.plan.spi;
|
||||
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface FetchableCollectionElement extends FetchOwner, CopyableReturn {
|
||||
@Override
|
||||
public FetchableCollectionElement makeCopy(CopyContext copyContext);
|
||||
|
||||
public CollectionReference getCollectionReference();
|
||||
}
|
||||
|
|
|
@ -49,16 +49,20 @@ import org.hibernate.loader.plan.spi.AbstractSingularAttributeFetch;
|
|||
import org.hibernate.loader.plan.spi.CollectionFetch;
|
||||
import org.hibernate.loader.plan.spi.CollectionReference;
|
||||
import org.hibernate.loader.plan.spi.CollectionReturn;
|
||||
import org.hibernate.loader.plan.spi.CompositeElementGraph;
|
||||
import org.hibernate.loader.plan.spi.CompositeFetch;
|
||||
import org.hibernate.loader.plan.spi.CompositeFetchOwnerDelegate;
|
||||
import org.hibernate.loader.plan.spi.EntityFetch;
|
||||
import org.hibernate.loader.plan.spi.EntityReference;
|
||||
import org.hibernate.loader.plan.spi.EntityReturn;
|
||||
import org.hibernate.loader.plan.spi.Fetch;
|
||||
import org.hibernate.loader.plan.spi.FetchOwner;
|
||||
import org.hibernate.loader.plan.spi.FetchOwnerDelegate;
|
||||
import org.hibernate.loader.plan.spi.IdentifierDescription;
|
||||
import org.hibernate.loader.plan.spi.Return;
|
||||
import org.hibernate.loader.spi.ResultSetProcessingContext;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.Loadable;
|
||||
import org.hibernate.persister.spi.HydratedCompoundValueHandler;
|
||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.AttributeDefinition;
|
||||
|
@ -66,9 +70,11 @@ import org.hibernate.persister.walking.spi.CollectionDefinition;
|
|||
import org.hibernate.persister.walking.spi.CollectionElementDefinition;
|
||||
import org.hibernate.persister.walking.spi.CollectionIndexDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionElementDefinition;
|
||||
import org.hibernate.persister.walking.spi.EntityDefinition;
|
||||
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
|
||||
import org.hibernate.persister.walking.spi.WalkingException;
|
||||
import org.hibernate.type.CompositeType;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
import static org.hibernate.loader.spi.ResultSetProcessingContext.IdentifierResolutionContext;
|
||||
|
@ -192,7 +198,12 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
|||
|
||||
final FetchOwner identifierAttributeCollector;
|
||||
if ( entityIdentifierDefinition.isEncapsulated() ) {
|
||||
identifierAttributeCollector = new EncapsulatedIdentifierAttributeCollector( entityReference );
|
||||
if ( entityIdentifierDefinition.getEntityDefinition().getEntityPersister().getIdentifierType().isComponentType() ) {
|
||||
identifierAttributeCollector = new EncapsulatedCompositeIdentifierAttributeCollector( entityReference );
|
||||
}
|
||||
else {
|
||||
identifierAttributeCollector = new EncapsulatedIdentifierAttributeCollector( entityReference );
|
||||
}
|
||||
}
|
||||
else {
|
||||
identifierAttributeCollector = new NonEncapsulatedIdentifierAttributeCollector( entityReference );
|
||||
|
@ -307,6 +318,35 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
|||
// - the element graph pushed while starting would be popped in finishing/Entity/finishingComposite
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startingCompositeElement(CompositionElementDefinition compositeElementDefinition) {
|
||||
System.out.println(
|
||||
String.format(
|
||||
"%s Starting composite collection element for (%s)",
|
||||
StringHelper.repeat( ">>", fetchOwnerStack.size() ),
|
||||
compositeElementDefinition.getCollectionDefinition().getCollectionPersister().getRole()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finishingCompositeElement(CompositionElementDefinition compositeElementDefinition) {
|
||||
// pop the current fetch owner, and make sure what we just popped represents this composition
|
||||
final FetchOwner poppedFetchOwner = popFromStack();
|
||||
|
||||
if ( ! CompositeElementGraph.class.isInstance( poppedFetchOwner ) ) {
|
||||
throw new WalkingException( "Mismatched FetchOwner from stack on pop" );
|
||||
}
|
||||
|
||||
// NOTE : not much else we can really check here atm since on the walking spi side we do not have path
|
||||
|
||||
log.tracef(
|
||||
"%s Finished composite element for : %s",
|
||||
StringHelper.repeat( "<<", fetchOwnerStack.size() ),
|
||||
compositeElementDefinition.getCollectionDefinition().getCollectionPersister().getRole()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finishingCollection(CollectionDefinition collectionDefinition) {
|
||||
// pop the current fetch owner, and make sure what we just popped represents this collection
|
||||
|
@ -513,6 +553,11 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
|||
return entityReference.getEntityPersister();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNullable(Fetch fetch) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdentifierDescription getIdentifierDescription() {
|
||||
return entityReference.getIdentifierDescription();
|
||||
|
@ -596,6 +641,13 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
|||
}
|
||||
}
|
||||
|
||||
protected static abstract class AbstractCompositeIdentifierAttributeCollector extends AbstractIdentifierAttributeCollector {
|
||||
|
||||
public AbstractCompositeIdentifierAttributeCollector(EntityReference entityReference) {
|
||||
super( entityReference );
|
||||
}
|
||||
}
|
||||
|
||||
protected static class EncapsulatedIdentifierAttributeCollector extends AbstractIdentifierAttributeCollector {
|
||||
private final PropertyPath propertyPath;
|
||||
|
||||
|
@ -613,17 +665,76 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType(Fetch fetch) {
|
||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getColumnNames(Fetch fetch) {
|
||||
return ( (Loadable) entityReference.getEntityPersister() ).getIdentifierColumnNames();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyPath getPropertyPath() {
|
||||
return propertyPath;
|
||||
}
|
||||
}
|
||||
|
||||
protected static class NonEncapsulatedIdentifierAttributeCollector extends AbstractIdentifierAttributeCollector {
|
||||
protected static class EncapsulatedCompositeIdentifierAttributeCollector extends AbstractCompositeIdentifierAttributeCollector {
|
||||
private final PropertyPath propertyPath;
|
||||
|
||||
public EncapsulatedCompositeIdentifierAttributeCollector(EntityReference entityReference) {
|
||||
super( entityReference );
|
||||
this.propertyPath = ( (FetchOwner) entityReference ).getPropertyPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IdentifierDescription buildIdentifierDescription() {
|
||||
return new IdentifierDescriptionImpl(
|
||||
entityReference,
|
||||
identifierFetches.toArray( new AbstractSingularAttributeFetch[ identifierFetches.size() ] ),
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyPath getPropertyPath() {
|
||||
return propertyPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType(Fetch fetch) {
|
||||
if ( !fetch.getOwnerPropertyName().equals( entityReference.getEntityPersister().getIdentifierPropertyName() ) ) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
"Fetch owner property name [%s] is not the same as the identifier property name [%s].",
|
||||
fetch.getOwnerPropertyName(),
|
||||
entityReference.getEntityPersister().getIdentifierPropertyName()
|
||||
)
|
||||
);
|
||||
}
|
||||
return entityReference.getEntityPersister().getIdentifierType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getColumnNames(Fetch fetch) {
|
||||
return ( (Loadable) entityReference.getEntityPersister() ).getIdentifierColumnNames();
|
||||
}
|
||||
}
|
||||
|
||||
protected static class NonEncapsulatedIdentifierAttributeCollector extends AbstractCompositeIdentifierAttributeCollector {
|
||||
private final PropertyPath propertyPath;
|
||||
private final FetchOwnerDelegate fetchOwnerDelegate;
|
||||
|
||||
public NonEncapsulatedIdentifierAttributeCollector(EntityReference entityReference) {
|
||||
super( entityReference );
|
||||
this.propertyPath = ( (FetchOwner) entityReference ).getPropertyPath().append( "<id>" );
|
||||
this.fetchOwnerDelegate = new CompositeFetchOwnerDelegate(
|
||||
entityReference.getEntityPersister().getFactory(),
|
||||
(CompositeType) entityReference.getEntityPersister().getIdentifierType(),
|
||||
( (Loadable) entityReference.getEntityPersister() ).getIdentifierColumnNames()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -639,6 +750,24 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
|||
public PropertyPath getPropertyPath() {
|
||||
return propertyPath;
|
||||
}
|
||||
|
||||
|
||||
public Type getType(Fetch fetch) {
|
||||
if ( !fetch.getOwnerPropertyName().equals( entityReference.getEntityPersister().getIdentifierPropertyName() ) ) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
"Fetch owner property name [%s] is not the same as the identifier property name [%s].",
|
||||
fetch.getOwnerPropertyName(),
|
||||
entityReference.getEntityPersister().getIdentifierPropertyName()
|
||||
)
|
||||
);
|
||||
}
|
||||
return fetchOwnerDelegate.getType( fetch );
|
||||
}
|
||||
|
||||
public String[] getColumnNames(Fetch fetch) {
|
||||
return fetchOwnerDelegate.getColumnNames( fetch );
|
||||
}
|
||||
}
|
||||
|
||||
private static class IdentifierDescriptionImpl implements IdentifierDescription {
|
||||
|
|
|
@ -80,10 +80,14 @@ import org.hibernate.persister.entity.EntityPersister;
|
|||
import org.hibernate.persister.entity.Loadable;
|
||||
import org.hibernate.persister.entity.PropertyMapping;
|
||||
import org.hibernate.persister.entity.Queryable;
|
||||
import org.hibernate.persister.walking.internal.CompositionSingularSubAttributesHelper;
|
||||
import org.hibernate.persister.walking.spi.AttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.AttributeSource;
|
||||
import org.hibernate.persister.walking.spi.CollectionDefinition;
|
||||
import org.hibernate.persister.walking.spi.CollectionElementDefinition;
|
||||
import org.hibernate.persister.walking.spi.CollectionIndexDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionElementDefinition;
|
||||
import org.hibernate.persister.walking.spi.EntityDefinition;
|
||||
import org.hibernate.pretty.MessageHelper;
|
||||
import org.hibernate.sql.Alias;
|
||||
|
@ -1941,7 +1945,6 @@ public abstract class AbstractCollectionPersister
|
|||
|
||||
public abstract FilterAliasGenerator getFilterAliasGenerator(final String rootAlias);
|
||||
|
||||
|
||||
// ColectionDefinition impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@Override
|
||||
|
@ -2007,12 +2010,42 @@ public abstract class AbstractCollectionPersister
|
|||
}
|
||||
|
||||
@Override
|
||||
public CompositionDefinition toCompositeDefinition() {
|
||||
public CompositionElementDefinition toCompositeElementDefinition() {
|
||||
final String propertyName = role.substring( entityName.length() + 1 );
|
||||
final int propertyIndex = ownerPersister.getEntityMetamodel().getPropertyIndex( propertyName );
|
||||
|
||||
if ( ! getType().isComponentType() ) {
|
||||
throw new IllegalStateException( "Cannot treat entity collection element type as composite" );
|
||||
}
|
||||
// todo : implement
|
||||
throw new NotYetImplementedException();
|
||||
|
||||
return new CompositionElementDefinition() {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return getElementType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeSource getSource() {
|
||||
// TODO: what if this is a collection w/in an encapsulated composition attribute?
|
||||
// should return the encapsulated composition attribute instead???
|
||||
return getOwnerEntityPersister();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<AttributeDefinition> getAttributes() {
|
||||
return CompositionSingularSubAttributesHelper.getCompositionElementSubAttributes( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionDefinition getCollectionDefinition() {
|
||||
return AbstractCollectionPersister.this;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -59,7 +59,6 @@ import org.hibernate.cache.spi.entry.ReferenceCacheEntryImpl;
|
|||
import org.hibernate.cache.spi.entry.StandardCacheEntryImpl;
|
||||
import org.hibernate.cache.spi.entry.StructuredCacheEntry;
|
||||
import org.hibernate.cache.spi.entry.UnstructuredCacheEntry;
|
||||
import org.hibernate.cfg.NotYetImplementedException;
|
||||
import org.hibernate.dialect.lock.LockingStrategy;
|
||||
import org.hibernate.engine.OptimisticLockStyle;
|
||||
import org.hibernate.engine.internal.StatefulPersistenceContext;
|
||||
|
@ -111,12 +110,7 @@ import org.hibernate.metamodel.relational.DerivedValue;
|
|||
import org.hibernate.metamodel.relational.Value;
|
||||
import org.hibernate.persister.walking.internal.EntityIdentifierDefinitionHelper;
|
||||
import org.hibernate.persister.walking.spi.AttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.AttributeSource;
|
||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||
import org.hibernate.persister.walking.spi.EncapsulatedEntityIdentifierDefinition;
|
||||
import org.hibernate.persister.walking.spi.EntityDefinition;
|
||||
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
|
||||
import org.hibernate.persister.walking.spi.NonEncapsulatedEntityIdentifierDefinition;
|
||||
import org.hibernate.pretty.MessageHelper;
|
||||
import org.hibernate.property.BackrefPropertyAccessor;
|
||||
import org.hibernate.sql.Alias;
|
||||
|
@ -132,7 +126,6 @@ import org.hibernate.sql.Update;
|
|||
import org.hibernate.tuple.entity.EntityMetamodel;
|
||||
import org.hibernate.tuple.entity.EntityTuplizer;
|
||||
import org.hibernate.type.AssociationType;
|
||||
import org.hibernate.type.ComponentType;
|
||||
import org.hibernate.type.CompositeType;
|
||||
import org.hibernate.type.EntityType;
|
||||
import org.hibernate.type.Type;
|
||||
|
|
|
@ -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" );
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -23,37 +23,16 @@
|
|||
*/
|
||||
package org.hibernate.persister.walking.internal;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.FetchStyle;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.engine.spi.CascadeStyle;
|
||||
import org.hibernate.engine.spi.CascadeStyles;
|
||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||
import org.hibernate.loader.PropertyPath;
|
||||
import org.hibernate.persister.entity.AbstractEntityPersister;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.Joinable;
|
||||
import org.hibernate.persister.spi.HydratedCompoundValueHandler;
|
||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.AssociationKey;
|
||||
import org.hibernate.persister.walking.spi.AttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.AttributeSource;
|
||||
import org.hibernate.persister.walking.spi.CollectionDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||
import org.hibernate.persister.walking.spi.EncapsulatedEntityIdentifierDefinition;
|
||||
import org.hibernate.persister.walking.spi.EntityDefinition;
|
||||
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
|
||||
import org.hibernate.persister.walking.spi.NonEncapsulatedEntityIdentifierDefinition;
|
||||
import org.hibernate.persister.walking.spi.WalkingException;
|
||||
import org.hibernate.type.AssociationType;
|
||||
import org.hibernate.type.ComponentType;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
import static org.hibernate.engine.internal.JoinHelper.getLHSColumnNames;
|
||||
import static org.hibernate.engine.internal.JoinHelper.getLHSTableName;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
|
@ -78,12 +57,13 @@ public class EntityIdentifierDefinitionHelper {
|
|||
};
|
||||
}
|
||||
|
||||
public static EntityIdentifierDefinition buildEncapsulatedCompositeIdentifierDefinition(final AbstractEntityPersister entityPersister) {
|
||||
public static EntityIdentifierDefinition buildEncapsulatedCompositeIdentifierDefinition(
|
||||
final AbstractEntityPersister entityPersister) {
|
||||
|
||||
return new EncapsulatedEntityIdentifierDefinition() {
|
||||
@Override
|
||||
public AttributeDefinition getAttributeDefinition() {
|
||||
return new CompositeAttributeDefinitionAdapter( entityPersister );
|
||||
return new CompositionDefinitionAdapter( entityPersister );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -102,7 +82,7 @@ public class EntityIdentifierDefinitionHelper {
|
|||
return new NonEncapsulatedEntityIdentifierDefinition() {
|
||||
@Override
|
||||
public Iterable<AttributeDefinition> getAttributes() {
|
||||
return new CompositeAttributeDefinitionAdapter( entityPersister ).getAttributes();
|
||||
return CompositionSingularSubAttributesHelper.getIdentifierSubAttributes( entityPersister );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -154,160 +134,20 @@ public class EntityIdentifierDefinitionHelper {
|
|||
}
|
||||
}
|
||||
|
||||
private static class CompositeAttributeDefinitionAdapter extends AttributeDefinitionAdapter implements CompositionDefinition {
|
||||
private static class CompositionDefinitionAdapter extends AttributeDefinitionAdapter implements CompositionDefinition {
|
||||
|
||||
CompositeAttributeDefinitionAdapter(AbstractEntityPersister entityPersister) {
|
||||
CompositionDefinitionAdapter(AbstractEntityPersister entityPersister) {
|
||||
super( entityPersister );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "<identifier-property:" + getName() + ">";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<AttributeDefinition> getAttributes() {
|
||||
return new Iterable<AttributeDefinition>() {
|
||||
@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" );
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
return CompositionSingularSubAttributesHelper.getIdentifierSubAttributes( getEntityPersister() );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -55,6 +55,9 @@ public interface AssociationVisitationStrategy {
|
|||
public void startingComposite(CompositionDefinition compositionDefinition);
|
||||
public void finishingComposite(CompositionDefinition compositionDefinition);
|
||||
|
||||
public void startingCompositeElement(CompositionElementDefinition compositionElementDefinition);
|
||||
public void finishingCompositeElement(CompositionElementDefinition compositionElementDefinition);
|
||||
|
||||
public boolean startingAttribute(AttributeDefinition attributeDefinition);
|
||||
public void finishingAttribute(AttributeDefinition attributeDefinition);
|
||||
}
|
||||
|
|
|
@ -35,5 +35,5 @@ public interface CollectionElementDefinition {
|
|||
|
||||
public EntityDefinition toEntityDefinition();
|
||||
|
||||
public CompositionDefinition toCompositeDefinition();
|
||||
public CompositionElementDefinition toCompositeElementDefinition();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -28,21 +28,12 @@ import java.util.Set;
|
|||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.FetchStyle;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.engine.spi.CascadeStyle;
|
||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.loader.PropertyPath;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.Joinable;
|
||||
import org.hibernate.persister.spi.HydratedCompoundValueHandler;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
import static org.hibernate.engine.internal.JoinHelper.getRHSColumnNames;
|
||||
|
||||
/**
|
||||
* Provides model graph visitation based on the defined metadata (as opposed to based on the incoming graph
|
||||
* as we see in cascade processing). In layman terms, we are walking the graph of the users model as defined by
|
||||
|
@ -211,7 +202,7 @@ public class MetadataDrivenModelGraphVisitor {
|
|||
strategy.startingCollectionElements( elementDefinition );
|
||||
|
||||
if ( elementDefinition.getType().isComponentType() ) {
|
||||
visitCompositeDefinition( elementDefinition.toCompositeDefinition() );
|
||||
visitCompositeElementDefinition( elementDefinition.toCompositeElementDefinition() );
|
||||
}
|
||||
else if ( elementDefinition.getType().isEntityType() ) {
|
||||
visitEntityDefinition( elementDefinition.toEntityDefinition() );
|
||||
|
@ -220,6 +211,13 @@ public class MetadataDrivenModelGraphVisitor {
|
|||
strategy.finishingCollectionElements( elementDefinition );
|
||||
}
|
||||
|
||||
private void visitCompositeElementDefinition(CompositionElementDefinition compositionElementDefinition) {
|
||||
strategy.startingCompositeElement( compositionElementDefinition );
|
||||
|
||||
visitAttributes( compositionElementDefinition );
|
||||
|
||||
strategy.finishingCompositeElement( compositionElementDefinition );
|
||||
}
|
||||
|
||||
private final Set<AssociationKey> visitedAssociationKeys = new HashSet<AssociationKey>();
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ public abstract class AbstractCompositeBasedAttribute
|
|||
private final int ownerAttributeNumber;
|
||||
|
||||
public AbstractCompositeBasedAttribute(
|
||||
AbstractCompositionDefinition source,
|
||||
AbstractCompositionAttribute source,
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
int attributeNumber,
|
||||
String attributeName,
|
||||
|
@ -55,7 +55,7 @@ public abstract class AbstractCompositeBasedAttribute
|
|||
}
|
||||
|
||||
@Override
|
||||
public AbstractCompositionDefinition getSource() {
|
||||
return (AbstractCompositionDefinition) super.getSource();
|
||||
public AbstractCompositionAttribute getSource() {
|
||||
return (AbstractCompositionAttribute) super.getSource();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,9 +48,9 @@ import static org.hibernate.engine.internal.JoinHelper.getRHSColumnNames;
|
|||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractCompositionDefinition extends AbstractNonIdentifierAttribute implements
|
||||
public abstract class AbstractCompositionAttribute extends AbstractNonIdentifierAttribute implements
|
||||
CompositionDefinition {
|
||||
protected AbstractCompositionDefinition(
|
||||
protected AbstractCompositionAttribute(
|
||||
AttributeSource source,
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
int attributeNumber,
|
||||
|
@ -120,41 +120,41 @@ public abstract class AbstractCompositionDefinition extends AbstractNonIdentifie
|
|||
}
|
||||
|
||||
return new CompositeBasedAssociationAttribute(
|
||||
AbstractCompositionDefinition.this,
|
||||
AbstractCompositionAttribute.this,
|
||||
sessionFactory(),
|
||||
subAttributeNumber,
|
||||
name,
|
||||
(AssociationType) type,
|
||||
new BaselineAttributeInformation.Builder()
|
||||
.setInsertable( AbstractCompositionDefinition.this.isInsertable() )
|
||||
.setUpdateable( AbstractCompositionDefinition.this.isUpdateable() )
|
||||
.setInsertGenerated( AbstractCompositionDefinition.this.isInsertGenerated() )
|
||||
.setUpdateGenerated( AbstractCompositionDefinition.this.isUpdateGenerated() )
|
||||
.setInsertable( AbstractCompositionAttribute.this.isInsertable() )
|
||||
.setUpdateable( AbstractCompositionAttribute.this.isUpdateable() )
|
||||
.setInsertGenerated( AbstractCompositionAttribute.this.isInsertGenerated() )
|
||||
.setUpdateGenerated( AbstractCompositionAttribute.this.isUpdateGenerated() )
|
||||
.setNullable( getType().getPropertyNullability()[subAttributeNumber] )
|
||||
.setDirtyCheckable( true )
|
||||
.setVersionable( AbstractCompositionDefinition.this.isVersionable() )
|
||||
.setVersionable( AbstractCompositionAttribute.this.isVersionable() )
|
||||
.setCascadeStyle( getType().getCascadeStyle( subAttributeNumber ) )
|
||||
.setFetchMode( getType().getFetchMode( subAttributeNumber ) )
|
||||
.createInformation(),
|
||||
AbstractCompositionDefinition.this.attributeNumber(),
|
||||
AbstractCompositionAttribute.this.attributeNumber(),
|
||||
associationKey
|
||||
);
|
||||
}
|
||||
else if ( type.isComponentType() ) {
|
||||
return new CompositionBasedCompositionAttribute(
|
||||
AbstractCompositionDefinition.this,
|
||||
AbstractCompositionAttribute.this,
|
||||
sessionFactory(),
|
||||
subAttributeNumber,
|
||||
name,
|
||||
(CompositeType) type,
|
||||
new BaselineAttributeInformation.Builder()
|
||||
.setInsertable( AbstractCompositionDefinition.this.isInsertable() )
|
||||
.setUpdateable( AbstractCompositionDefinition.this.isUpdateable() )
|
||||
.setInsertGenerated( AbstractCompositionDefinition.this.isInsertGenerated() )
|
||||
.setUpdateGenerated( AbstractCompositionDefinition.this.isUpdateGenerated() )
|
||||
.setInsertable( AbstractCompositionAttribute.this.isInsertable() )
|
||||
.setUpdateable( AbstractCompositionAttribute.this.isUpdateable() )
|
||||
.setInsertGenerated( AbstractCompositionAttribute.this.isInsertGenerated() )
|
||||
.setUpdateGenerated( AbstractCompositionAttribute.this.isUpdateGenerated() )
|
||||
.setNullable( getType().getPropertyNullability()[subAttributeNumber] )
|
||||
.setDirtyCheckable( true )
|
||||
.setVersionable( AbstractCompositionDefinition.this.isVersionable() )
|
||||
.setVersionable( AbstractCompositionAttribute.this.isVersionable() )
|
||||
.setCascadeStyle( getType().getCascadeStyle( subAttributeNumber ) )
|
||||
.setFetchMode( getType().getFetchMode( subAttributeNumber ) )
|
||||
.createInformation()
|
||||
|
@ -162,19 +162,19 @@ public abstract class AbstractCompositionDefinition extends AbstractNonIdentifie
|
|||
}
|
||||
else {
|
||||
return new CompositeBasedBasicAttribute(
|
||||
AbstractCompositionDefinition.this,
|
||||
AbstractCompositionAttribute.this,
|
||||
sessionFactory(),
|
||||
subAttributeNumber,
|
||||
name,
|
||||
type,
|
||||
new BaselineAttributeInformation.Builder()
|
||||
.setInsertable( AbstractCompositionDefinition.this.isInsertable() )
|
||||
.setUpdateable( AbstractCompositionDefinition.this.isUpdateable() )
|
||||
.setInsertGenerated( AbstractCompositionDefinition.this.isInsertGenerated() )
|
||||
.setUpdateGenerated( AbstractCompositionDefinition.this.isUpdateGenerated() )
|
||||
.setInsertable( AbstractCompositionAttribute.this.isInsertable() )
|
||||
.setUpdateable( AbstractCompositionAttribute.this.isUpdateable() )
|
||||
.setInsertGenerated( AbstractCompositionAttribute.this.isInsertGenerated() )
|
||||
.setUpdateGenerated( AbstractCompositionAttribute.this.isUpdateGenerated() )
|
||||
.setNullable( getType().getPropertyNullability()[subAttributeNumber] )
|
||||
.setDirtyCheckable( true )
|
||||
.setVersionable( AbstractCompositionDefinition.this.isVersionable() )
|
||||
.setVersionable( AbstractCompositionAttribute.this.isVersionable() )
|
||||
.setCascadeStyle( getType().getCascadeStyle( subAttributeNumber ) )
|
||||
.setFetchMode( getType().getFetchMode( subAttributeNumber ) )
|
||||
.createInformation()
|
||||
|
@ -196,7 +196,7 @@ public abstract class AbstractCompositionDefinition extends AbstractNonIdentifie
|
|||
return ( (EntityDefinition) getSource() ).getEntityPersister();
|
||||
}
|
||||
else {
|
||||
return ( (AbstractCompositionDefinition) getSource() ).locateOwningPersister();
|
||||
return ( (AbstractCompositionAttribute) getSource() ).locateOwningPersister();
|
||||
}
|
||||
}
|
||||
|
|
@ -55,7 +55,7 @@ public class CompositeBasedAssociationAttribute
|
|||
private Joinable joinable;
|
||||
|
||||
public CompositeBasedAssociationAttribute(
|
||||
AbstractCompositionDefinition source,
|
||||
AbstractCompositionAttribute source,
|
||||
SessionFactoryImplementor factory,
|
||||
int attributeNumber,
|
||||
String attributeName,
|
||||
|
|
|
@ -32,7 +32,7 @@ import org.hibernate.type.CompositeType;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class CompositionBasedCompositionAttribute
|
||||
extends AbstractCompositionDefinition
|
||||
extends AbstractCompositionAttribute
|
||||
implements CompositionDefinition {
|
||||
public CompositionBasedCompositionAttribute(
|
||||
CompositionDefinition source,
|
||||
|
|
|
@ -25,7 +25,7 @@ package org.hibernate.tuple.entity;
|
|||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.tuple.component.AbstractCompositionDefinition;
|
||||
import org.hibernate.tuple.component.AbstractCompositionAttribute;
|
||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||
import org.hibernate.tuple.BaselineAttributeInformation;
|
||||
import org.hibernate.type.CompositeType;
|
||||
|
@ -34,7 +34,7 @@ import org.hibernate.type.CompositeType;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class EntityBasedCompositionAttribute
|
||||
extends AbstractCompositionDefinition
|
||||
extends AbstractCompositionAttribute
|
||||
implements CompositionDefinition {
|
||||
|
||||
public EntityBasedCompositionAttribute(
|
||||
|
|
|
@ -42,6 +42,7 @@ import javax.persistence.EnumType;
|
|||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -60,6 +61,7 @@ import org.hibernate.loader.spi.LoadQueryAliasResolutionContext;
|
|||
import org.hibernate.loader.spi.NamedParameterContext;
|
||||
import org.hibernate.loader.spi.NoOpLoadPlanAdvisor;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.test.component.cascading.toone.PersonalInfo;
|
||||
import org.hibernate.testing.FailureExpected;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.hibernate.testing.junit4.ExtraAssertions;
|
||||
|
@ -128,12 +130,15 @@ public class EncapsulatedCompositeAttributeResultSetProcessorTest extends BaseCo
|
|||
session.close();
|
||||
}
|
||||
|
||||
/*
|
||||
@Test
|
||||
public void testNestedCompositeElementCollectionProcessing() throws Exception {
|
||||
// create some test data
|
||||
Session session = openSession();
|
||||
session.beginTransaction();
|
||||
Person person = new Person();
|
||||
person.id = 1;
|
||||
person.name = "Joe Blow";
|
||||
session.save( person );
|
||||
Customer customer = new Customer();
|
||||
customer.id = 1L;
|
||||
Investment investment1 = new Investment();
|
||||
|
@ -142,6 +147,7 @@ public class EncapsulatedCompositeAttributeResultSetProcessorTest extends BaseCo
|
|||
investment1.monetaryAmount = new MonetaryAmount();
|
||||
investment1.monetaryAmount.currency = MonetaryAmount.CurrencyCode.USD;
|
||||
investment1.monetaryAmount.amount = BigDecimal.valueOf( 1234, 2 );
|
||||
investment1.performedBy = person;
|
||||
Investment investment2 = new Investment();
|
||||
investment2.description = "bond";
|
||||
investment2.date = new Date();
|
||||
|
@ -173,11 +179,11 @@ public class EncapsulatedCompositeAttributeResultSetProcessorTest extends BaseCo
|
|||
// clean up test data
|
||||
session = openSession();
|
||||
session.beginTransaction();
|
||||
session.createQuery( "delete Customer" ).executeUpdate();
|
||||
session.delete( customerWork.investments.get( 0 ).performedBy );
|
||||
session.delete( customerWork );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
}
|
||||
*/
|
||||
|
||||
private List<?> getResults(EntityPersister entityPersister ) {
|
||||
final SingleRootReturnLoadPlanBuilderStrategy strategy = new SingleRootReturnLoadPlanBuilderStrategy(
|
||||
|
@ -288,6 +294,7 @@ public class EncapsulatedCompositeAttributeResultSetProcessorTest extends BaseCo
|
|||
private MonetaryAmount monetaryAmount;
|
||||
private String description;
|
||||
private Date date;
|
||||
private Person performedBy;
|
||||
|
||||
@Embedded
|
||||
public MonetaryAmount getMonetaryAmount() {
|
||||
|
@ -308,6 +315,13 @@ public class EncapsulatedCompositeAttributeResultSetProcessorTest extends BaseCo
|
|||
public void setDate(Date date) {
|
||||
this.date = date;
|
||||
}
|
||||
@ManyToOne
|
||||
public Person getPerformedBy() {
|
||||
return performedBy;
|
||||
}
|
||||
public void setPerformedBy(Person performedBy) {
|
||||
this.performedBy = performedBy;
|
||||
}
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
|
|
|
@ -38,6 +38,7 @@ import org.hibernate.persister.walking.spi.CollectionDefinition;
|
|||
import org.hibernate.persister.walking.spi.CollectionElementDefinition;
|
||||
import org.hibernate.persister.walking.spi.CollectionIndexDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionElementDefinition;
|
||||
import org.hibernate.persister.walking.spi.EntityDefinition;
|
||||
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
|
||||
import org.hibernate.persister.walking.spi.MetadataDrivenModelGraphVisitor;
|
||||
|
@ -168,6 +169,28 @@ public class BasicWalkingTest extends BaseCoreFunctionalTestCase {
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startingCompositeElement(CompositionElementDefinition compositionElementDefinition) {
|
||||
System.out.println(
|
||||
String.format(
|
||||
"%s Starting composite (%s)",
|
||||
StringHelper.repeat( ">>", ++depth ),
|
||||
compositionElementDefinition.toString()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finishingCompositeElement(CompositionElementDefinition compositionElementDefinition) {
|
||||
System.out.println(
|
||||
String.format(
|
||||
"%s Finishing composite (%s)",
|
||||
StringHelper.repeat( ">>", depth-- ),
|
||||
compositionElementDefinition.toString()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startingAttribute(AttributeDefinition attributeDefinition) {
|
||||
System.out.println(
|
||||
|
|
Loading…
Reference in New Issue