Author: steve.ebersole(a)jboss.com
Date: 2010-05-20 01:37:43 -0400 (Thu, 20 May 2010)
New Revision: 19563
Added:
core/trunk/core/src/main/java/org/hibernate/loader/PropertyPath.java
Modified:
core/trunk/core/src/main/java/org/hibernate/impl/SessionImpl.java
core/trunk/core/src/main/java/org/hibernate/loader/AbstractEntityJoinWalker.java
core/trunk/core/src/main/java/org/hibernate/loader/JoinWalker.java
core/trunk/core/src/main/java/org/hibernate/loader/Loader.java
core/trunk/core/src/main/java/org/hibernate/loader/OuterJoinableAssociation.java
core/trunk/core/src/main/java/org/hibernate/loader/collection/BasicCollectionJoinWalker.java
core/trunk/core/src/main/java/org/hibernate/loader/collection/OneToManyJoinWalker.java
core/trunk/core/src/main/java/org/hibernate/loader/criteria/CriteriaJoinWalker.java
core/trunk/core/src/main/java/org/hibernate/loader/entity/EntityJoinWalker.java
core/trunk/core/src/main/java/org/hibernate/loader/entity/EntityLoader.java
Log:
HHH-2277 - bidirectional <key-many-to-one> both lazy=false fetch=join lead to
infinite loop
Modified: core/trunk/core/src/main/java/org/hibernate/impl/SessionImpl.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/impl/SessionImpl.java 2010-05-19 18:29:45
UTC (rev 19562)
+++ core/trunk/core/src/main/java/org/hibernate/impl/SessionImpl.java 2010-05-20 05:37:43
UTC (rev 19563)
@@ -1022,9 +1022,11 @@
public Object internalLoad(String entityName, Serializable id, boolean eager, boolean
nullable) throws HibernateException {
// todo : remove
- LoadEventListener.LoadType type = nullable ?
- LoadEventListener.INTERNAL_LOAD_NULLABLE :
- eager ? LoadEventListener.INTERNAL_LOAD_EAGER :
LoadEventListener.INTERNAL_LOAD_LAZY;
+ LoadEventListener.LoadType type = nullable
+ ? LoadEventListener.INTERNAL_LOAD_NULLABLE
+ : eager
+ ? LoadEventListener.INTERNAL_LOAD_EAGER
+ : LoadEventListener.INTERNAL_LOAD_LAZY;
LoadEvent event = new LoadEvent(id, entityName, true, this);
fireLoad(event, type);
if ( !nullable ) {
Modified:
core/trunk/core/src/main/java/org/hibernate/loader/AbstractEntityJoinWalker.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/loader/AbstractEntityJoinWalker.java 2010-05-19
18:29:45 UTC (rev 19562)
+++
core/trunk/core/src/main/java/org/hibernate/loader/AbstractEntityJoinWalker.java 2010-05-20
05:37:43 UTC (rev 19563)
@@ -29,7 +29,6 @@
import java.util.Iterator;
import org.hibernate.FetchMode;
-import org.hibernate.LockMode;
import org.hibernate.MappingException;
import org.hibernate.LockOptions;
import org.hibernate.engine.CascadeStyle;
@@ -42,7 +41,6 @@
import org.hibernate.sql.JoinFragment;
import org.hibernate.sql.Select;
import org.hibernate.type.AssociationType;
-import org.hibernate.util.CollectionHelper;
/**
* Abstract walker for walkers which begin at an entity (criteria
@@ -76,23 +74,20 @@
final String whereString,
final String orderByString,
final LockOptions lockOptions) throws MappingException {
+ initAll( whereString, orderByString, lockOptions, AssociationInitCallback.NO_CALLBACK
);
+ }
+
+ protected final void initAll(
+ final String whereString,
+ final String orderByString,
+ final LockOptions lockOptions,
+ final AssociationInitCallback callback) throws MappingException {
walkEntityTree( persister, getAlias() );
List allAssociations = new ArrayList();
- allAssociations.addAll(associations);
- allAssociations.add(
- new OuterJoinableAssociation(
- persister.getEntityType(),
- null,
- null,
- alias,
- JoinFragment.LEFT_OUTER_JOIN,
- null,
- getFactory(),
- CollectionHelper.EMPTY_MAP
- )
- );
- initPersisters(allAssociations, lockOptions);
- initStatementString( whereString, orderByString, lockOptions);
+ allAssociations.addAll( associations );
+ allAssociations.add( OuterJoinableAssociation.createRoot( persister.getEntityType(),
alias, getFactory() ) );
+ initPersisters( allAssociations, lockOptions, callback );
+ initStatementString( whereString, orderByString, lockOptions );
}
protected final void initProjection(
@@ -162,17 +157,18 @@
return isJoinedFetchEnabledInMapping( config, type );
}
- protected final boolean isJoinFetchEnabledByProfile(OuterJoinLoadable persister, String
path, int propertyNumber) {
+ protected final boolean isJoinFetchEnabledByProfile(OuterJoinLoadable persister,
PropertyPath path, int propertyNumber) {
if ( !getLoadQueryInfluencers().hasEnabledFetchProfiles() ) {
// perf optimization
return false;
}
// ugh, this stuff has to be made easier...
+ final String fullPath = path.getFullPath();
String rootPropertyName = persister.getSubclassPropertyName( propertyNumber );
- int pos = path.lastIndexOf( rootPropertyName );
+ int pos = fullPath.lastIndexOf( rootPropertyName );
String relativePropertyPath = pos >= 0
- ? path.substring( pos )
+ ? fullPath.substring( pos )
: rootPropertyName;
String fetchRole = persister.getEntityName() + "." + relativePropertyPath;
Modified: core/trunk/core/src/main/java/org/hibernate/loader/JoinWalker.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/loader/JoinWalker.java 2010-05-19 18:29:45
UTC (rev 19562)
+++ core/trunk/core/src/main/java/org/hibernate/loader/JoinWalker.java 2010-05-20 05:37:43
UTC (rev 19563)
@@ -40,8 +40,6 @@
import org.hibernate.engine.JoinHelper;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.LoadQueryInfluencers;
-import org.hibernate.engine.profile.FetchProfile;
-import org.hibernate.engine.profile.Fetch;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.persister.entity.EntityPersister;
@@ -93,7 +91,8 @@
this.loadQueryInfluencers = loadQueryInfluencers;
}
-
+
+
public String[] getCollectionSuffixes() {
return collectionSuffixes;
}
@@ -194,7 +193,7 @@
final AssociationType type,
final String[] aliasedLhsColumns,
final String alias,
- final String path,
+ final PropertyPath path,
int currentDepth,
final int joinType) throws MappingException {
if ( joinType >= 0 ) {
@@ -209,7 +208,7 @@
}
}
- protected String getWithClause(String path) {
+ protected String getWithClause(PropertyPath path) {
return "";
}
@@ -221,7 +220,7 @@
final AssociationType type,
final String[] aliasedLhsColumns,
final String alias,
- String path,
+ final PropertyPath path,
final int currentDepth,
final int joinType) throws MappingException {
@@ -236,6 +235,7 @@
// only need to worry about restrictions (and not say adding more
// joins)
OuterJoinableAssociation assoc = new OuterJoinableAssociation(
+ path,
type,
alias,
aliasedLhsColumns,
@@ -245,7 +245,7 @@
getFactory(),
loadQueryInfluencers.getEnabledFilters()
);
- assoc.validateJoin( path );
+ assoc.validateJoin( path.getFullPath() );
associations.add( assoc );
int nextDepth = currentDepth + 1;
@@ -277,7 +277,7 @@
* Walk the association tree for an entity, adding associations which should
* be join fetched to the {@link #associations} inst var. This form is the
* entry point into the walking for a given entity, starting the recursive
- * calls into {@link #walkEntityTree(OuterJoinLoadable, String, String, int)}.
+ * calls into {@link #walkEntityTree(org.hibernate.persister.entity.OuterJoinLoadable,
String, PropertyPath ,int)}.
*
* @param persister The persister representing the entity to be walked.
* @param alias The (root) alias to use for this entity/persister.
@@ -286,15 +286,14 @@
protected final void walkEntityTree(
OuterJoinLoadable persister,
String alias) throws MappingException {
- walkEntityTree( persister, alias, "", 0 );
+ walkEntityTree( persister, alias, new PropertyPath(), 0 );
}
/**
* For a collection role, return a list of associations to be fetched by outerjoin
*/
- protected final void walkCollectionTree(QueryableCollection persister, String alias)
- throws MappingException {
- walkCollectionTree(persister, alias, "", 0);
+ protected final void walkCollectionTree(QueryableCollection persister, String alias)
throws MappingException {
+ walkCollectionTree( persister, alias, new PropertyPath(), 0 );
//TODO: when this is the entry point, we should use an INNER_JOIN for fetching the
many-to-many elements!
}
@@ -302,11 +301,10 @@
* For a collection role, return a list of associations to be fetched by outerjoin
*/
private void walkCollectionTree(
- final QueryableCollection persister,
- final String alias,
- final String path,
- final int currentDepth)
- throws MappingException {
+ final QueryableCollection persister,
+ final String alias,
+ final PropertyPath path,
+ final int currentDepth) throws MappingException {
if ( persister.isOneToMany() ) {
walkEntityTree(
@@ -338,7 +336,7 @@
!useInnerJoin,
currentDepth - 1,
null //operations which cascade as far as the collection also cascade to collection
elements
- );
+ );
addAssociationToJoinTreeIfNecessary(
associationType,
aliasedLhsColumns,
@@ -382,7 +380,7 @@
final OuterJoinLoadable persister,
final int propertyNumber,
final String alias,
- final String path,
+ final PropertyPath path,
final boolean nullable,
final int currentDepth) throws MappingException {
String[] aliasedLhsColumns = JoinHelper.getAliasedLHSColumnNames(
@@ -393,10 +391,10 @@
);
String lhsTable = JoinHelper.getLHSTableName(associationType, propertyNumber,
persister);
- String subpath = subPath( path, persister.getSubclassPropertyName(propertyNumber) );
+ PropertyPath subPath = path.append( persister.getSubclassPropertyName(propertyNumber)
);
int joinType = getJoinType(
persister,
- subpath,
+ subPath,
propertyNumber,
associationType,
persister.getFetchMode( propertyNumber ),
@@ -410,7 +408,7 @@
associationType,
aliasedLhsColumns,
alias,
- subpath,
+ subPath,
currentDepth,
joinType
);
@@ -436,7 +434,7 @@
*/
protected int getJoinType(
OuterJoinLoadable persister,
- final String path,
+ final PropertyPath path,
int propertyNumber,
AssociationType associationType,
FetchMode metadataFetchMode,
@@ -476,7 +474,7 @@
protected int getJoinType(
AssociationType associationType,
FetchMode config,
- String path,
+ PropertyPath path,
String lhsTable,
String[] lhsColumns,
boolean nullable,
@@ -498,18 +496,18 @@
* Walk the association tree for an entity, adding associations which should
* be join fetched to the {@link #associations} inst var. This form is the
* entry point into the walking for a given entity, starting the recursive
- * calls into {@link #walkEntityTree(OuterJoinLoadable, String, String, int)}.
+ * calls into {@link #walkEntityTree(org.hibernate.persister.entity.OuterJoinLoadable,
String, PropertyPath ,int)}.
*
* @param persister The persister representing the entity to be walked.
* @param alias The (root) alias to use for this entity/persister.
- * @param path todo this seems to be rooted at the *root* persister
+ * @param path The property path to the entity being walked
* @param currentDepth The current join depth
* @throws org.hibernate.MappingException ???
*/
private void walkEntityTree(
final OuterJoinLoadable persister,
final String alias,
- final String path,
+ final PropertyPath path,
final int currentDepth) throws MappingException {
int n = persister.countSubclassProperties();
for ( int i = 0; i < n; i++ ) {
@@ -527,13 +525,13 @@
}
else if ( type.isComponentType() ) {
walkComponentTree(
- ( AbstractComponentType ) type,
- i,
- 0,
- persister,
- alias,
- subPath( path, persister.getSubclassPropertyName(i) ),
- currentDepth
+ ( AbstractComponentType ) type,
+ i,
+ 0,
+ persister,
+ alias,
+ path.append( persister.getSubclassPropertyName(i) ),
+ currentDepth
);
}
}
@@ -559,7 +557,7 @@
int begin,
final OuterJoinLoadable persister,
final String alias,
- final String path,
+ final PropertyPath path,
final int currentDepth) throws MappingException {
Type[] types = componentType.getSubtypes();
String[] propertyNames = componentType.getPropertyNames();
@@ -574,11 +572,11 @@
);
String lhsTable = JoinHelper.getLHSTableName(associationType, propertyNumber,
persister);
- String subpath = subPath( path, propertyNames[i] );
+ final PropertyPath subPath = path.append( propertyNames[i] );
final boolean[] propertyNullability = componentType.getPropertyNullability();
final int joinType = getJoinType(
persister,
- subpath,
+ subPath,
propertyNumber,
associationType,
componentType.getFetchMode(i),
@@ -592,21 +590,21 @@
associationType,
aliasedLhsColumns,
alias,
- subpath,
+ subPath,
currentDepth,
joinType
);
}
else if ( types[i].isComponentType() ) {
- String subpath = subPath( path, propertyNames[i] );
+ final PropertyPath subPath = path.append( propertyNames[i] );
walkComponentTree(
( AbstractComponentType ) types[i],
propertyNumber,
begin,
persister,
alias,
- subpath,
+ subPath,
currentDepth
);
}
@@ -623,7 +621,7 @@
final String[] cols,
final QueryableCollection persister,
final String alias,
- final String path,
+ final PropertyPath path,
final int currentDepth) throws MappingException {
Type[] types = compositeType.getSubtypes();
@@ -640,12 +638,12 @@
// (or even a property-ref) in a composite-element:
String[] aliasedLhsColumns = StringHelper.qualify(alias, lhsColumns);
- String subpath = subPath( path, propertyNames[i] );
+ final PropertyPath subPath = path.append( propertyNames[i] );
final boolean[] propertyNullability = compositeType.getPropertyNullability();
final int joinType = getJoinType(
associationType,
compositeType.getFetchMode(i),
- subpath,
+ subPath,
persister.getTableName(),
lhsColumns,
propertyNullability==null || propertyNullability[i],
@@ -656,19 +654,19 @@
associationType,
aliasedLhsColumns,
alias,
- subpath,
+ subPath,
currentDepth,
joinType
);
}
else if ( types[i].isComponentType() ) {
- String subpath = subPath( path, propertyNames[i] );
+ final PropertyPath subPath = path.append( propertyNames[i] );
walkCompositeElementTree(
(AbstractComponentType) types[i],
lhsColumns,
persister,
alias,
- subpath,
+ subPath,
currentDepth
);
}
@@ -678,18 +676,6 @@
}
/**
- * Extend the path by the given property name
- */
- private static String subPath(String path, String property) {
- if ( path==null || path.length()==0) {
- return property;
- }
- else {
- return StringHelper.qualify(path, property);
- }
- }
-
- /**
* Use an inner join if it is a non-null association and this
* is the "first" join in a series
*/
@@ -746,10 +732,7 @@
return type.isEntityType() && isJoinedFetchEnabledInMapping(config, type) ;
}
- protected String generateTableAlias(
- final int n,
- final String path,
- final Joinable joinable) {
+ protected String generateTableAlias(final int n, final PropertyPath path, final Joinable
joinable) {
return StringHelper.generateAlias( joinable.getName(), n );
}
@@ -761,10 +744,7 @@
* Used to detect circularities in the joined graph, note that
* this method is side-effecty
*/
- protected boolean isDuplicateAssociation(
- final String foreignKeyTable,
- final String[] foreignKeyColumns
- ) {
+ protected boolean isDuplicateAssociation(final String foreignKeyTable, final String[]
foreignKeyColumns) {
AssociationKey associationKey = new AssociationKey(foreignKeyColumns,
foreignKeyTable);
return !visitedAssociationKeys.add( associationKey );
}
@@ -773,11 +753,7 @@
* Used to detect circularities in the joined graph, note that
* this method is side-effecty
*/
- protected boolean isDuplicateAssociation(
- final String lhsTable,
- final String[] lhsColumnNames,
- final AssociationType type
- ) {
+ protected boolean isDuplicateAssociation(final String lhsTable, final String[]
lhsColumnNames, final AssociationType type) {
final String foreignKeyTable;
final String[] foreignKeyColumns;
if ( type.getForeignKeyDirection()==ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT ) {
@@ -815,20 +791,23 @@
* Should we join this association?
*/
protected boolean isJoinable(
- final int joinType,
- final Set visitedAssociationKeys,
- final String lhsTable,
- final String[] lhsColumnNames,
- final AssociationType type,
- final int depth
- ) {
- if (joinType<0) return false;
+ final int joinType,
+ final Set visitedAssociationKeys,
+ final String lhsTable,
+ final String[] lhsColumnNames,
+ final AssociationType type,
+ final int depth) {
+
+ if ( joinType < 0 ) {
+ return false;
+ }
- if (joinType==JoinFragment.INNER_JOIN) return true;
-
+ if ( joinType == JoinFragment.INNER_JOIN ) {
+ return true;
+ }
+
Integer maxFetchDepth = getFactory().getSettings().getMaximumFetchDepth();
- final boolean tooDeep = maxFetchDepth!=null &&
- depth >= maxFetchDepth.intValue();
+ final boolean tooDeep = maxFetchDepth!=null && depth >=
maxFetchDepth.intValue();
return !tooDeep && !isDuplicateAssociation(lhsTable, lhsColumnNames, type);
}
@@ -985,8 +964,22 @@
initPersisters( associations, new LockOptions(lockMode));
}
+ protected static interface AssociationInitCallback {
+ public static final AssociationInitCallback NO_CALLBACK = new AssociationInitCallback()
{
+ public void associationProcessed(OuterJoinableAssociation oja, int position) {
+ }
+ };
+
+ public void associationProcessed(OuterJoinableAssociation oja, int position);
+ }
protected void initPersisters(final List associations, final LockOptions lockOptions)
throws MappingException {
-
+ initPersisters( associations, lockOptions, AssociationInitCallback.NO_CALLBACK );
+ }
+
+ protected void initPersisters(
+ final List associations,
+ final LockOptions lockOptions,
+ final AssociationInitCallback callback) throws MappingException {
final int joins = countEntityPersisters(associations);
final int collections = countCollectionPersisters(associations);
@@ -1013,6 +1006,7 @@
aliases[i] = oj.getRHSAlias();
owners[i] = oj.getOwner(associations);
ownerAssociationTypes[i] = (EntityType) oj.getJoinableType();
+ callback.associationProcessed( oj, i );
i++;
}
@@ -1029,11 +1023,12 @@
if ( collPersister.isOneToMany() ) {
persisters[i] = (Loadable) collPersister.getElementPersister();
aliases[i] = oj.getRHSAlias();
+ callback.associationProcessed( oj, i );
i++;
}
}
}
-
+
if ( ArrayHelper.isAllNegative(owners) ) owners = null;
if ( collectionOwners!=null && ArrayHelper.isAllNegative(collectionOwners) ) {
collectionOwners = null;
Modified: core/trunk/core/src/main/java/org/hibernate/loader/Loader.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/loader/Loader.java 2010-05-19 18:29:45 UTC
(rev 19562)
+++ core/trunk/core/src/main/java/org/hibernate/loader/Loader.java 2010-05-20 05:37:43 UTC
(rev 19563)
@@ -173,6 +173,10 @@
return null;
}
+ protected int[][] getCompositeKeyManyToOneTargetIndices() {
+ return null;
+ }
+
/**
* What lock options does this load entities with?
*
@@ -599,20 +603,8 @@
final Loadable[] persisters = getEntityPersisters();
final int entitySpan = persisters.length;
+ extractKeysFromResultSet( persisters, queryParameters, resultSet, session, keys,
lockModesArray, hydratedObjects );
- for ( int i = 0; i < entitySpan; i++ ) {
- keys[i] = getKeyFromResultSet(
- i,
- persisters[i],
- i == entitySpan - 1 ?
- queryParameters.getOptionalId() :
- null,
- resultSet,
- session
- );
- //TODO: the i==entitySpan-1 bit depends upon subclass implementation (very bad)
- }
-
registerNonExists( keys, persisters, session );
// this call is side-effecty
@@ -648,6 +640,98 @@
}
+ protected void extractKeysFromResultSet(
+ Loadable[] persisters,
+ QueryParameters queryParameters,
+ ResultSet resultSet,
+ SessionImplementor session,
+ EntityKey[] keys,
+ LockMode[] lockModes,
+ List hydratedObjects) throws SQLException {
+ final int entitySpan = persisters.length;
+
+ final int numberOfPersistersToProcess;
+ final Serializable optionalId = queryParameters.getOptionalId();
+ if ( isSingleRowLoader() && optionalId != null ) {
+ keys[ entitySpan - 1 ] = new EntityKey( optionalId, persisters[ entitySpan - 1 ],
session.getEntityMode() );
+ // skip the last persister below...
+ numberOfPersistersToProcess = entitySpan - 1;
+ }
+ else {
+ numberOfPersistersToProcess = entitySpan;
+ }
+
+ final Object[] hydratedKeyState = new Object[numberOfPersistersToProcess];
+
+ for ( int i = 0; i < numberOfPersistersToProcess; i++ ) {
+ final Type idType = persisters[i].getIdentifierType();
+ hydratedKeyState[i] = idType.hydrate( resultSet,
getEntityAliases()[i].getSuffixedKeyAliases(), session, null );
+ }
+
+ for ( int i = 0; i < numberOfPersistersToProcess; i++ ) {
+ final Type idType = persisters[i].getIdentifierType();
+ if ( idType.isComponentType() && getCompositeKeyManyToOneTargetIndices() !=
null ) {
+ // we may need to force resolve any key-many-to-one(s)
+ int[] keyManyToOneTargetIndices = getCompositeKeyManyToOneTargetIndices()[i];
+ // todo : better solution is to order the index processing based on target indices
+ // that would account for multiple levels whereas this scheme does not
+ if ( keyManyToOneTargetIndices != null ) {
+ for ( int targetIndex : keyManyToOneTargetIndices ) {
+ if ( targetIndex < numberOfPersistersToProcess ) {
+ final Type targetIdType = persisters[targetIndex].getIdentifierType();
+ final Serializable targetId = (Serializable) targetIdType.resolve(
+ hydratedKeyState[targetIndex],
+ session,
+ null
+ );
+ // todo : need a way to signal that this key is resolved and its data resolved
+ keys[targetIndex] = new EntityKey( targetId, persisters[targetIndex],
session.getEntityMode() );
+ }
+
+ // this part copied from #getRow, this section could be refactored out
+ Object object = session.getEntityUsingInterceptor( keys[targetIndex] );
+ if ( object != null ) {
+ //its already loaded so don't need to hydrate it
+ instanceAlreadyLoaded(
+ resultSet,
+ targetIndex,
+ persisters[targetIndex],
+ keys[targetIndex],
+ object,
+ lockModes[targetIndex],
+ session
+ );
+ }
+ else {
+ object = instanceNotYetLoaded(
+ resultSet,
+ targetIndex,
+ persisters[targetIndex],
+ getEntityAliases()[targetIndex].getRowIdAlias(),
+ keys[targetIndex],
+ lockModes[targetIndex],
+ getOptionalObjectKey( queryParameters, session ),
+ queryParameters.getOptionalObject(),
+ hydratedObjects,
+ session
+ );
+ }
+ }
+ }
+ }
+ final Serializable resolvedId = (Serializable) idType.resolve( hydratedKeyState[i],
session, null );
+ keys[i] = resolvedId == null ? null : new EntityKey( resolvedId, persisters[i],
session.getEntityMode() );
+ }
+ }
+
+ private Serializable determineResultId(SessionImplementor session, Serializable
optionalId, Type idType, Serializable resolvedId) {
+ final boolean idIsResultId = optionalId != null
+ && resolvedId != null
+ && idType.isEqual( optionalId, resolvedId, session.getEntityMode(), factory
);
+ final Serializable resultId = idIsResultId ? optionalId : resolvedId;
+ return resultId;
+ }
+
protected void applyPostLoadLocks(Object[] row, LockMode[] lockModesArray,
SessionImplementor session) {
}
Modified:
core/trunk/core/src/main/java/org/hibernate/loader/OuterJoinableAssociation.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/loader/OuterJoinableAssociation.java 2010-05-19
18:29:45 UTC (rev 19562)
+++
core/trunk/core/src/main/java/org/hibernate/loader/OuterJoinableAssociation.java 2010-05-20
05:37:43 UTC (rev 19563)
@@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
- * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * Copyright (c) 2010, 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 Middleware LLC.
+ * 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
@@ -20,7 +20,6 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
- *
*/
package org.hibernate.loader;
@@ -35,6 +34,7 @@
import org.hibernate.sql.JoinFragment;
import org.hibernate.type.AssociationType;
import org.hibernate.type.EntityType;
+import org.hibernate.util.CollectionHelper;
/**
* Part of the Hibernate SQL rendering internals. This class represents
@@ -43,6 +43,7 @@
* @author Gavin King
*/
public final class OuterJoinableAssociation {
+ private final PropertyPath propertyPath;
private final AssociationType joinableType;
private final Joinable joinable;
private final String lhsAlias; // belong to other persister
@@ -53,7 +54,25 @@
private final String on;
private final Map enabledFilters;
+ public static OuterJoinableAssociation createRoot(
+ AssociationType joinableType,
+ String alias,
+ SessionFactoryImplementor factory) {
+ return new OuterJoinableAssociation(
+ new PropertyPath(),
+ joinableType,
+ null,
+ null,
+ alias,
+ JoinFragment.LEFT_OUTER_JOIN,
+ null,
+ factory,
+ CollectionHelper.EMPTY_MAP
+ );
+ }
+
public OuterJoinableAssociation(
+ PropertyPath propertyPath,
AssociationType joinableType,
String lhsAlias,
String[] lhsColumns,
@@ -62,6 +81,7 @@
String withClause,
SessionFactoryImplementor factory,
Map enabledFilters) throws MappingException {
+ this.propertyPath = propertyPath;
this.joinableType = joinableType;
this.lhsAlias = lhsAlias;
this.lhsColumns = lhsColumns;
@@ -74,14 +94,26 @@
this.enabledFilters = enabledFilters; // needed later for many-to-many/filter
application
}
+ public PropertyPath getPropertyPath() {
+ return propertyPath;
+ }
+
public int getJoinType() {
return joinType;
}
+ public String getLhsAlias() {
+ return lhsAlias;
+ }
+
public String getRHSAlias() {
return rhsAlias;
}
+ public String getRhsAlias() {
+ return rhsAlias;
+ }
+
private boolean isOneToOne() {
if ( joinableType.isEntityType() ) {
EntityType etype = (EntityType) joinableType;
@@ -90,7 +122,6 @@
else {
return false;
}
-
}
public AssociationType getJoinableType() {
@@ -150,12 +181,8 @@
}
public void validateJoin(String path) throws MappingException {
- if (
- rhsColumns==null ||
- lhsColumns==null ||
- lhsColumns.length!=rhsColumns.length ||
- lhsColumns.length==0
- ) {
+ if ( rhsColumns==null || lhsColumns==null
+ || lhsColumns.length!=rhsColumns.length || lhsColumns.length==0 ) {
throw new MappingException("invalid join columns for association: " +
path);
}
}
Added: core/trunk/core/src/main/java/org/hibernate/loader/PropertyPath.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/loader/PropertyPath.java
(rev 0)
+++ core/trunk/core/src/main/java/org/hibernate/loader/PropertyPath.java 2010-05-20
05:37:43 UTC (rev 19563)
@@ -0,0 +1,90 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, 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;
+
+import org.hibernate.util.StringHelper;
+
+/**
+* TODO : javadoc
+*
+* @author Steve Ebersole
+*/
+public class PropertyPath {
+ private final PropertyPath parent;
+ private final String property;
+ private final String fullPath;
+
+ public PropertyPath(PropertyPath parent, String property) {
+ this.parent = parent;
+ this.property = property;
+
+ final String prefix;
+ if ( parent != null ) {
+ final String resolvedParent = parent.getFullPath();
+ if ( StringHelper.isEmpty( resolvedParent ) ) {
+ prefix = "";
+ }
+ else {
+ prefix = resolvedParent + '.';
+ }
+ }
+ else {
+ prefix = "";
+ }
+ this.fullPath = prefix + property;
+ }
+
+ public PropertyPath(String property) {
+ this( null, property );
+ }
+
+ public PropertyPath() {
+ this( "" );
+ }
+
+ public PropertyPath append(String property) {
+ return new PropertyPath( this, property );
+ }
+
+ public PropertyPath getParent() {
+ return parent;
+ }
+
+ public String getProperty() {
+ return property;
+ }
+
+ public String getFullPath() {
+ return fullPath;
+ }
+
+ public boolean isRoot() {
+ return parent == null && StringHelper.isEmpty( property );
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + '[' + fullPath + ']';
+ }
+}
Modified:
core/trunk/core/src/main/java/org/hibernate/loader/collection/BasicCollectionJoinWalker.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/loader/collection/BasicCollectionJoinWalker.java 2010-05-19
18:29:45 UTC (rev 19562)
+++
core/trunk/core/src/main/java/org/hibernate/loader/collection/BasicCollectionJoinWalker.java 2010-05-20
05:37:43 UTC (rev 19563)
@@ -27,8 +27,6 @@
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
-import java.util.Map;
-import java.util.Set;
import org.hibernate.FetchMode;
import org.hibernate.LockMode;
@@ -38,12 +36,12 @@
import org.hibernate.engine.CascadeStyle;
import org.hibernate.loader.BasicLoader;
import org.hibernate.loader.OuterJoinableAssociation;
+import org.hibernate.loader.PropertyPath;
import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.sql.JoinFragment;
import org.hibernate.sql.Select;
import org.hibernate.type.AssociationType;
-import org.hibernate.util.CollectionHelper;
import org.hibernate.util.StringHelper;
/**
@@ -73,18 +71,7 @@
List allAssociations = new ArrayList();
allAssociations.addAll(associations);
- allAssociations.add(
- new OuterJoinableAssociation(
- collectionPersister.getCollectionType(),
- null,
- null,
- alias,
- JoinFragment.LEFT_OUTER_JOIN,
- null,
- getFactory(),
- CollectionHelper.EMPTY_MAP
- )
- );
+ allAssociations.add( OuterJoinableAssociation.createRoot(
collectionPersister.getCollectionType(), alias, getFactory() ) );
initPersisters(allAssociations, LockMode.NONE);
initStatementString(alias, batchSize, subquery);
}
@@ -155,7 +142,7 @@
protected int getJoinType(
OuterJoinLoadable persister,
- String path,
+ PropertyPath path,
int propertyNumber,
AssociationType associationType,
FetchMode metadataFetchMode,
@@ -177,7 +164,7 @@
currentDepth
);
//we can use an inner join for the many-to-many
- if ( joinType==JoinFragment.LEFT_OUTER_JOIN && "".equals(path) ) {
+ if ( joinType==JoinFragment.LEFT_OUTER_JOIN && path.isRoot() ) {
joinType=JoinFragment.INNER_JOIN;
}
return joinType;
Modified:
core/trunk/core/src/main/java/org/hibernate/loader/collection/OneToManyJoinWalker.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/loader/collection/OneToManyJoinWalker.java 2010-05-19
18:29:45 UTC (rev 19562)
+++
core/trunk/core/src/main/java/org/hibernate/loader/collection/OneToManyJoinWalker.java 2010-05-20
05:37:43 UTC (rev 19563)
@@ -79,17 +79,7 @@
List allAssociations = new ArrayList();
allAssociations.addAll(associations);
- allAssociations.add( new OuterJoinableAssociation(
- oneToManyPersister.getCollectionType(),
- null,
- null,
- alias,
- JoinFragment.LEFT_OUTER_JOIN,
- null,
- getFactory(),
- CollectionHelper.EMPTY_MAP
- ) );
-
+ allAssociations.add( OuterJoinableAssociation.createRoot(
oneToManyPersister.getCollectionType(), alias, getFactory() ) );
initPersisters(allAssociations, LockMode.NONE);
initStatementString(elementPersister, alias, batchSize, subquery);
}
Modified:
core/trunk/core/src/main/java/org/hibernate/loader/criteria/CriteriaJoinWalker.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/loader/criteria/CriteriaJoinWalker.java 2010-05-19
18:29:45 UTC (rev 19562)
+++
core/trunk/core/src/main/java/org/hibernate/loader/criteria/CriteriaJoinWalker.java 2010-05-20
05:37:43 UTC (rev 19563)
@@ -30,7 +30,6 @@
import org.hibernate.Criteria;
import org.hibernate.FetchMode;
-import org.hibernate.LockMode;
import org.hibernate.MappingException;
import org.hibernate.LockOptions;
import org.hibernate.engine.CascadeStyle;
@@ -38,12 +37,12 @@
import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.impl.CriteriaImpl;
import org.hibernate.loader.AbstractEntityJoinWalker;
+import org.hibernate.loader.PropertyPath;
import org.hibernate.persister.entity.Joinable;
import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.persister.entity.Queryable;
import org.hibernate.type.AssociationType;
import org.hibernate.type.Type;
-import org.hibernate.type.TypeFactory;
import org.hibernate.util.ArrayHelper;
/**
@@ -121,7 +120,7 @@
protected int getJoinType(
OuterJoinLoadable persister,
- final String path,
+ final PropertyPath path,
int propertyNumber,
AssociationType associationType,
FetchMode metadataFetchMode,
@@ -130,15 +129,15 @@
String[] lhsColumns,
final boolean nullable,
final int currentDepth) throws MappingException {
- if ( translator.isJoin( path ) ) {
- return translator.getJoinType( path );
+ if ( translator.isJoin( path.getFullPath() ) ) {
+ return translator.getJoinType( path.getFullPath() );
}
else {
if ( translator.hasProjection() ) {
return -1;
}
else {
- FetchMode fetchMode = translator.getRootCriteria().getFetchMode( path );
+ FetchMode fetchMode = translator.getRootCriteria().getFetchMode( path.getFullPath()
);
if ( isDefaultFetchMode( fetchMode ) ) {
if ( isJoinFetchEnabledByProfile( persister, path, propertyNumber ) ) {
return getJoinType( nullable, currentDepth );
@@ -174,14 +173,14 @@
protected int getJoinType(
AssociationType associationType,
FetchMode config,
- String path,
+ PropertyPath path,
String lhsTable,
String[] lhsColumns,
boolean nullable,
int currentDepth,
CascadeStyle cascadeStyle) throws MappingException {
- return ( translator.isJoin( path ) ?
- translator.getJoinType( path ) :
+ return ( translator.isJoin( path.getFullPath() ) ?
+ translator.getJoinType( path.getFullPath() ) :
super.getJoinType(
associationType,
config,
@@ -208,9 +207,9 @@
( (Queryable) getPersister() ).filterFragment( getAlias(),
getLoadQueryInfluencers().getEnabledFilters() );
}
- protected String generateTableAlias(int n, String path, Joinable joinable) {
+ protected String generateTableAlias(int n, PropertyPath path, Joinable joinable) {
if ( joinable.consumesEntityAlias() ) {
- final Criteria subcriteria = translator.getCriteria(path);
+ final Criteria subcriteria = translator.getCriteria( path.getFullPath() );
String sqlAlias = subcriteria==null ? null : translator.getSQLAlias(subcriteria);
if (sqlAlias!=null) {
userAliasList.add( subcriteria.getAlias() ); //alias may be null
@@ -235,8 +234,8 @@
return "criteria query";
}
- protected String getWithClause(String path) {
- return translator.getWithClause(path);
+ protected String getWithClause(PropertyPath path) {
+ return translator.getWithClause( path.getFullPath() );
}
}
Modified: core/trunk/core/src/main/java/org/hibernate/loader/entity/EntityJoinWalker.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/loader/entity/EntityJoinWalker.java 2010-05-19
18:29:45 UTC (rev 19562)
+++
core/trunk/core/src/main/java/org/hibernate/loader/entity/EntityJoinWalker.java 2010-05-20
05:37:43 UTC (rev 19563)
@@ -24,18 +24,27 @@
*/
package org.hibernate.loader.entity;
+import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import org.hibernate.FetchMode;
import org.hibernate.LockMode;
+import org.hibernate.LockOptions;
import org.hibernate.MappingException;
-import org.hibernate.LockOptions;
import org.hibernate.engine.CascadeStyle;
+import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.engine.SessionFactoryImplementor;
-import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.loader.AbstractEntityJoinWalker;
+import org.hibernate.loader.OuterJoinableAssociation;
+import org.hibernate.loader.PropertyPath;
+import org.hibernate.persister.collection.QueryableCollection;
+import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.type.AssociationType;
+import org.hibernate.type.ComponentType;
+import org.hibernate.type.EntityType;
+import org.hibernate.type.Type;
/**
* A walker for loaders that fetch entities
@@ -46,13 +55,14 @@
public class EntityJoinWalker extends AbstractEntityJoinWalker {
private final LockOptions lockOptions = new LockOptions();
+ private final int[][] compositeKeyManyToOneTargetIndices;
public EntityJoinWalker(
OuterJoinLoadable persister,
String[] uniqueKey,
int batchSize,
LockMode lockMode,
- SessionFactoryImplementor factory,
+ final SessionFactoryImplementor factory,
LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
super( persister, factory, loadQueryInfluencers );
@@ -62,7 +72,9 @@
//include the discriminator and class-level where, but not filters
.append( persister.filterFragment( getAlias(), Collections.EMPTY_MAP ) );
- initAll( whereCondition.toString(), "", lockOptions);
+ AssociationInitCallbackImpl callback = new AssociationInitCallbackImpl( factory );
+ initAll( whereCondition.toString(), "", lockOptions, callback );
+ this.compositeKeyManyToOneTargetIndices = callback.resolve();
}
public EntityJoinWalker(
@@ -79,12 +91,14 @@
//include the discriminator and class-level where, but not filters
.append( persister.filterFragment( getAlias(), Collections.EMPTY_MAP ) );
- initAll( whereCondition.toString(), "", lockOptions);
+ AssociationInitCallbackImpl callback = new AssociationInitCallbackImpl( factory );
+ initAll( whereCondition.toString(), "", lockOptions, callback );
+ this.compositeKeyManyToOneTargetIndices = callback.resolve();
}
protected int getJoinType(
OuterJoinLoadable persister,
- String path,
+ PropertyPath path,
int propertyNumber,
AssociationType associationType,
FetchMode metadataFetchMode,
@@ -116,5 +130,132 @@
public String getComment() {
return "load " + getPersister().getEntityName();
}
-
+
+ public int[][] getCompositeKeyManyToOneTargetIndices() {
+ return compositeKeyManyToOneTargetIndices;
+ }
+
+ private static class AssociationInitCallbackImpl implements AssociationInitCallback {
+ private final SessionFactoryImplementor factory;
+ private final HashMap<String,OuterJoinableAssociation> associationsByAlias
+ = new HashMap<String, OuterJoinableAssociation>();
+ private final HashMap<String,Integer> positionsByAlias = new HashMap<String,
Integer>();
+ private final ArrayList<String> aliasesForAssociationsWithCompositesIds
+ = new ArrayList<String>();
+
+ public AssociationInitCallbackImpl(SessionFactoryImplementor factory) {
+ this.factory = factory;
+ }
+
+ public void associationProcessed(OuterJoinableAssociation oja, int position) {
+ associationsByAlias.put( oja.getRhsAlias(), oja );
+ positionsByAlias.put( oja.getRhsAlias(), position );
+ EntityPersister entityPersister = null;
+ if ( oja.getJoinableType().isCollectionType() ) {
+ entityPersister = ( ( QueryableCollection) oja.getJoinable()
).getElementPersister();
+ }
+ else if ( oja.getJoinableType().isEntityType() ) {
+ entityPersister = ( EntityPersister ) oja.getJoinable();
+ }
+ if ( entityPersister != null
+ && entityPersister.getIdentifierType().isComponentType()
+ && !
entityPersister.getEntityMetamodel().getIdentifierProperty().isEmbedded()
+ && hasAssociation( (ComponentType) entityPersister.getIdentifierType() ) )
{
+ aliasesForAssociationsWithCompositesIds.add( oja.getRhsAlias() );
+ }
+ }
+
+ private boolean hasAssociation(ComponentType componentType) {
+ int i = 0;
+ for ( Type subType : componentType.getSubtypes() ) {
+ if ( subType.isEntityType() ) {
+ return true;
+ }
+ else if ( subType.isComponentType() && hasAssociation( ( (ComponentType)
subType ) ) ) {
+ return true;
+ }
+ i++;
+ }
+ return false;
+ }
+
+ public int[][] resolve() {
+ int[][] compositeKeyManyToOneTargetIndices = null;
+ for ( final String aliasWithCompositeId : aliasesForAssociationsWithCompositesIds ) {
+ final OuterJoinableAssociation joinWithCompositeId = associationsByAlias.get(
aliasWithCompositeId );
+ final ArrayList<Integer> keyManyToOneTargetIndices = new
ArrayList<Integer>();
+ // for each association with a composite id containing key-many-to-one(s), find the
bidirectional side of
+ // each key-many-to-one (if exists) to see if it is eager as well. If so, we need to
track the indices
+ EntityPersister entityPersister = null;
+ if ( joinWithCompositeId.getJoinableType().isCollectionType() ) {
+ entityPersister = ( ( QueryableCollection) joinWithCompositeId.getJoinable()
).getElementPersister();
+ }
+ else if ( joinWithCompositeId.getJoinableType().isEntityType() ) {
+ entityPersister = ( EntityPersister ) joinWithCompositeId.getJoinable();
+ }
+
+ findKeyManyToOneTargetIndices(
+ keyManyToOneTargetIndices,
+ joinWithCompositeId,
+ (ComponentType) entityPersister.getIdentifierType()
+ );
+
+ if ( ! keyManyToOneTargetIndices.isEmpty() ) {
+ if ( compositeKeyManyToOneTargetIndices == null ) {
+ compositeKeyManyToOneTargetIndices = new int[ associationsByAlias.size() ][];
+ }
+ int position = positionsByAlias.get( aliasWithCompositeId );
+ compositeKeyManyToOneTargetIndices[position] = new int[
keyManyToOneTargetIndices.size() ];
+ int i = 0;
+ for ( int index : keyManyToOneTargetIndices ) {
+ compositeKeyManyToOneTargetIndices[position][i] = index;
+ i++;
+ }
+ }
+ }
+ return compositeKeyManyToOneTargetIndices;
+ }
+
+ private void findKeyManyToOneTargetIndices(
+ ArrayList<Integer> keyManyToOneTargetIndices,
+ OuterJoinableAssociation joinWithCompositeId,
+ ComponentType componentType) {
+ for ( Type subType : componentType.getSubtypes() ) {
+ if ( subType.isEntityType() ) {
+ Integer index = locateKeyManyToOneTargetIndex( joinWithCompositeId, (EntityType)
subType );
+ if ( index != null ) {
+ keyManyToOneTargetIndices.add( index );
+ }
+ }
+ else if ( subType.isComponentType() ) {
+ findKeyManyToOneTargetIndices(
+ keyManyToOneTargetIndices,
+ joinWithCompositeId,
+ (ComponentType) subType
+ );
+ }
+ }
+ }
+
+ private Integer locateKeyManyToOneTargetIndex(OuterJoinableAssociation
joinWithCompositeId, EntityType keyManyToOneType) {
+ // the lhs (if one) is a likely candidate
+ if ( joinWithCompositeId.getLhsAlias() != null ) {
+ final OuterJoinableAssociation lhs = associationsByAlias.get(
joinWithCompositeId.getLhsAlias() );
+ if ( keyManyToOneType.getAssociatedEntityName( factory ).equals(
lhs.getJoinableType().getAssociatedEntityName( factory ) ) ) {
+ return positionsByAlias.get( lhs.getRhsAlias() );
+ }
+ }
+ // otherwise, seek out OuterJoinableAssociation which are RHS of given
OuterJoinableAssociation
+ // (joinWithCompositeId)
+ for ( OuterJoinableAssociation oja : associationsByAlias.values() ) {
+ if ( oja.getLhsAlias() != null && oja.getLhsAlias().equals(
joinWithCompositeId.getRhsAlias() ) ) {
+ if ( keyManyToOneType.equals( oja.getJoinableType() ) ) {
+ return positionsByAlias.get( oja.getLhsAlias() );
+ }
+ }
+ }
+ return null;
+ }
+ }
+
}
\ No newline at end of file
Modified: core/trunk/core/src/main/java/org/hibernate/loader/entity/EntityLoader.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/loader/entity/EntityLoader.java 2010-05-19
18:29:45 UTC (rev 19562)
+++ core/trunk/core/src/main/java/org/hibernate/loader/entity/EntityLoader.java 2010-05-20
05:37:43 UTC (rev 19563)
@@ -24,14 +24,12 @@
*/
package org.hibernate.loader.entity;
-import org.hibernate.HibernateException;
import org.hibernate.LockMode;
+import org.hibernate.LockOptions;
import org.hibernate.MappingException;
-import org.hibernate.LockOptions;
+import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
-import org.hibernate.engine.LoadQueryInfluencers;
-import org.hibernate.loader.JoinWalker;
import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.type.Type;
@@ -46,6 +44,7 @@
public class EntityLoader extends AbstractEntityLoader {
private final boolean batchLoader;
+ private final int[][] compositeKeyManyToOneTargetIndices;
public EntityLoader(
OuterJoinLoadable persister,
@@ -107,7 +106,7 @@
LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
super( persister, uniqueKeyType, factory, loadQueryInfluencers );
- JoinWalker walker = new EntityJoinWalker(
+ EntityJoinWalker walker = new EntityJoinWalker(
persister,
uniqueKey,
batchSize,
@@ -116,7 +115,7 @@
loadQueryInfluencers
);
initFromWalker( walker );
-
+ this.compositeKeyManyToOneTargetIndices =
walker.getCompositeKeyManyToOneTargetIndices();
postInstantiate();
batchLoader = batchSize > 1;
@@ -134,7 +133,7 @@
LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
super( persister, uniqueKeyType, factory, loadQueryInfluencers );
- JoinWalker walker = new EntityJoinWalker(
+ EntityJoinWalker walker = new EntityJoinWalker(
persister,
uniqueKey,
batchSize,
@@ -143,7 +142,7 @@
loadQueryInfluencers
);
initFromWalker( walker );
-
+ this.compositeKeyManyToOneTargetIndices =
walker.getCompositeKeyManyToOneTargetIndices();
postInstantiate();
batchLoader = batchSize > 1;
@@ -163,5 +162,8 @@
protected boolean isSingleRowLoader() {
return !batchLoader;
}
-
+
+ public int[][] getCompositeKeyManyToOneTargetIndices() {
+ return compositeKeyManyToOneTargetIndices;
+ }
}
\ No newline at end of file