Author: steve.ebersole(a)jboss.com
Date: 2008-08-15 17:20:15 -0400 (Fri, 15 Aug 2008)
New Revision: 15091
Added:
core/trunk/core/src/main/java/org/hibernate/UnknownProfileException.java
core/trunk/core/src/main/java/org/hibernate/engine/LoadQueryInfluencers.java
core/trunk/core/src/main/java/org/hibernate/engine/profile/
core/trunk/core/src/main/java/org/hibernate/engine/profile/Association.java
core/trunk/core/src/main/java/org/hibernate/engine/profile/Fetch.java
core/trunk/core/src/main/java/org/hibernate/engine/profile/FetchProfile.java
core/trunk/core/src/main/java/org/hibernate/mapping/FetchProfile.java
core/trunk/testsuite/src/test/java/org/hibernate/test/fetchprofiles/
core/trunk/testsuite/src/test/java/org/hibernate/test/fetchprofiles/basic/
core/trunk/testsuite/src/test/java/org/hibernate/test/fetchprofiles/basic/BasicFetchProfileTest.java
core/trunk/testsuite/src/test/java/org/hibernate/test/fetchprofiles/basic/Course.java
core/trunk/testsuite/src/test/java/org/hibernate/test/fetchprofiles/basic/CourseOffering.java
core/trunk/testsuite/src/test/java/org/hibernate/test/fetchprofiles/basic/Department.java
core/trunk/testsuite/src/test/java/org/hibernate/test/fetchprofiles/basic/Enrollment.java
core/trunk/testsuite/src/test/java/org/hibernate/test/fetchprofiles/basic/Mappings.hbm.xml
core/trunk/testsuite/src/test/java/org/hibernate/test/fetchprofiles/basic/Student.java
Modified:
core/trunk/core/src/main/java/org/hibernate/Session.java
core/trunk/core/src/main/java/org/hibernate/SessionFactory.java
core/trunk/core/src/main/java/org/hibernate/cfg/Configuration.java
core/trunk/core/src/main/java/org/hibernate/cfg/HbmBinder.java
core/trunk/core/src/main/java/org/hibernate/cfg/Mappings.java
core/trunk/core/src/main/java/org/hibernate/criterion/SubqueryExpression.java
core/trunk/core/src/main/java/org/hibernate/engine/SessionFactoryImplementor.java
core/trunk/core/src/main/java/org/hibernate/engine/SessionImplementor.java
core/trunk/core/src/main/java/org/hibernate/impl/SessionFactoryImpl.java
core/trunk/core/src/main/java/org/hibernate/impl/SessionImpl.java
core/trunk/core/src/main/java/org/hibernate/impl/StatelessSessionImpl.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/OuterJoinLoader.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/BasicCollectionLoader.java
core/trunk/core/src/main/java/org/hibernate/loader/collection/BatchingCollectionInitializer.java
core/trunk/core/src/main/java/org/hibernate/loader/collection/CollectionJoinWalker.java
core/trunk/core/src/main/java/org/hibernate/loader/collection/CollectionLoader.java
core/trunk/core/src/main/java/org/hibernate/loader/collection/OneToManyJoinWalker.java
core/trunk/core/src/main/java/org/hibernate/loader/collection/OneToManyLoader.java
core/trunk/core/src/main/java/org/hibernate/loader/collection/SubselectCollectionLoader.java
core/trunk/core/src/main/java/org/hibernate/loader/collection/SubselectOneToManyLoader.java
core/trunk/core/src/main/java/org/hibernate/loader/criteria/CriteriaJoinWalker.java
core/trunk/core/src/main/java/org/hibernate/loader/criteria/CriteriaLoader.java
core/trunk/core/src/main/java/org/hibernate/loader/entity/AbstractEntityLoader.java
core/trunk/core/src/main/java/org/hibernate/loader/entity/BatchingEntityLoader.java
core/trunk/core/src/main/java/org/hibernate/loader/entity/CascadeEntityJoinWalker.java
core/trunk/core/src/main/java/org/hibernate/loader/entity/CascadeEntityLoader.java
core/trunk/core/src/main/java/org/hibernate/loader/entity/CollectionElementLoader.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
core/trunk/core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java
core/trunk/core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java
core/trunk/core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java
core/trunk/core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java
core/trunk/core/src/main/java/org/hibernate/persister/entity/Loadable.java
core/trunk/core/src/main/resources/org/hibernate/hibernate-mapping-3.0.dtd
core/trunk/jmx/src/main/java/org/hibernate/jmx/SessionFactoryStub.java
core/trunk/testsuite/src/test/resources/hibernate.properties
Log:
HHH-3414 : fetch profiles, phase 1 : join fetching
Modified: core/trunk/core/src/main/java/org/hibernate/Session.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/Session.java 2008-08-15 21:03:38 UTC (rev
15090)
+++ core/trunk/core/src/main/java/org/hibernate/Session.java 2008-08-15 21:20:15 UTC (rev
15091)
@@ -813,4 +813,40 @@
* @see #disconnect()
*/
void reconnect(Connection connection) throws HibernateException;
+
+ /**
+ * Is a particular fetch profile enabled on this session?
+ *
+ * @param name The name of the profile to be checked.
+ * @return True if fetch profile is enabled; false if not.
+ * @throws UnknownProfileException Indicates that the given name does not
+ * match any known profile names
+ *
+ * @see org.hibernate.engine.profile.FetchProfile for discussion of this feature
+ */
+ public boolean isFetchProfileEnabled(String name) throws UnknownProfileException;
+
+ /**
+ * Enable a particular fetch profile on this session. No-op if requested
+ * profile is already enabled.
+ *
+ * @param name The name of the fetch profile to be enabled.
+ * @throws UnknownProfileException Indicates that the given name does not
+ * match any known profile names
+ *
+ * @see org.hibernate.engine.profile.FetchProfile for discussion of this feature
+ */
+ public void enableFetchProfile(String name) throws UnknownProfileException;
+
+ /**
+ * Disable a particular fetch profile on this session. No-op if requested
+ * profile is already disabled.
+ *
+ * @param name The name of the fetch profile to be disabled.
+ * @throws UnknownProfileException Indicates that the given name does not
+ * match any known profile names
+ *
+ * @see org.hibernate.engine.profile.FetchProfile for discussion of this feature
+ */
+ public void disableFetchProfile(String name) throws UnknownProfileException;
}
Modified: core/trunk/core/src/main/java/org/hibernate/SessionFactory.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/SessionFactory.java 2008-08-15 21:03:38
UTC (rev 15090)
+++ core/trunk/core/src/main/java/org/hibernate/SessionFactory.java 2008-08-15 21:20:15
UTC (rev 15091)
@@ -244,4 +244,13 @@
* @throws HibernateException If no filter defined with the given name.
*/
public FilterDefinition getFilterDefinition(String filterName) throws
HibernateException;
+
+ /**
+ * Determine if this session factory contains a fetch profile definition
+ * registered under the given name.
+ *
+ * @param name The name to check
+ * @return True if there is such a fetch profile; false otherwise.
+ */
+ public boolean containsFetchProfileDefition(String name);
}
Added: core/trunk/core/src/main/java/org/hibernate/UnknownProfileException.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/UnknownProfileException.java
(rev 0)
+++ core/trunk/core/src/main/java/org/hibernate/UnknownProfileException.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -0,0 +1,48 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC 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.
+ *
+ * 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;
+
+/**
+ * Used to indicate a request against an unknown profile name.
+ *
+ * @author Steve Ebersole
+ */
+public class UnknownProfileException extends HibernateException {
+ private final String name;
+
+ public UnknownProfileException(String name) {
+ super( "Unknow fetch profile [" + name + "]" );
+ this.name = name;
+ }
+
+ /**
+ * The unknown fetch profile name.
+ *
+ * @return The unknown fetch profile name.
+ */
+ public String getName() {
+ return name;
+ }
+}
Modified: core/trunk/core/src/main/java/org/hibernate/cfg/Configuration.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/cfg/Configuration.java 2008-08-15 21:03:38
UTC (rev 15090)
+++ core/trunk/core/src/main/java/org/hibernate/cfg/Configuration.java 2008-08-15 21:20:15
UTC (rev 15091)
@@ -114,6 +114,7 @@
import org.hibernate.mapping.SimpleValue;
import org.hibernate.mapping.Table;
import org.hibernate.mapping.UniqueKey;
+import org.hibernate.mapping.FetchProfile;
import org.hibernate.proxy.EntityNotFoundDelegate;
import org.hibernate.secure.JACCConfiguration;
import org.hibernate.tool.hbm2ddl.DatabaseMetadata;
@@ -163,6 +164,7 @@
*/
protected Map sqlResultSetMappings;
protected Map filterDefinitions;
+ protected Map fetchProfiles;
protected List secondPasses;
protected List propertyReferences;
// protected List extendsQueue;
@@ -202,6 +204,7 @@
entityResolver = XMLHelper.DEFAULT_DTD_RESOLVER;
eventListeners = new EventListeners();
filterDefinitions = new HashMap();
+ fetchProfiles = new HashMap();
// extendsQueue = new ArrayList();
extendsQueue = new HashMap();
auxiliaryDatabaseObjects = new ArrayList();
@@ -720,6 +723,7 @@
namingStrategy,
typeDefs,
filterDefinitions,
+ fetchProfiles,
extendsQueue,
auxiliaryDatabaseObjects,
tableNameBinding,
@@ -2181,6 +2185,14 @@
filterDefinitions.put( definition.getFilterName(), definition );
}
+ public Map getFetchProfiles() {
+ return fetchProfiles;
+ }
+
+ public void addFetchProfile(FetchProfile fetchProfile) {
+ fetchProfiles.put( fetchProfile.getName(), fetchProfile );
+ }
+
public void addAuxiliaryDatabaseObject(AuxiliaryDatabaseObject object) {
auxiliaryDatabaseObjects.add( object );
}
Modified: core/trunk/core/src/main/java/org/hibernate/cfg/HbmBinder.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/cfg/HbmBinder.java 2008-08-15 21:03:38 UTC
(rev 15090)
+++ core/trunk/core/src/main/java/org/hibernate/cfg/HbmBinder.java 2008-08-15 21:20:15 UTC
(rev 15091)
@@ -89,6 +89,7 @@
import org.hibernate.mapping.UnionSubclass;
import org.hibernate.mapping.UniqueKey;
import org.hibernate.mapping.Value;
+import org.hibernate.mapping.FetchProfile;
import org.hibernate.persister.entity.JoinedSubclassEntityPersister;
import org.hibernate.persister.entity.SingleTableEntityPersister;
import org.hibernate.persister.entity.UnionSubclassEntityPersister;
@@ -158,6 +159,9 @@
if ( "filter-def".equals( elementName ) ) {
parseFilterDef( element, mappings );
}
+ else if ( "fetch-profile".equals( elementName ) ) {
+ parseFetchProfile( element, mappings, null );
+ }
else if ( "typedef".equals( elementName ) ) {
bindTypeDef( element, mappings );
}
@@ -546,8 +550,13 @@
bindDom4jRepresentation( node, persistentClass, mappings, inheritedMetas );
bindMapRepresentation( node, persistentClass, mappings, inheritedMetas );
+ Iterator itr = node.elementIterator( "fetch-profile" );
+ while ( itr.hasNext() ) {
+ final Element profileElement = ( Element ) itr.next();
+ parseFetchProfile( profileElement, mappings, entityName );
+ }
+
bindPersistentClassCommonValues( node, persistentClass, mappings, inheritedMetas );
-
}
private static void bindPojoRepresentation(Element node, PersistentClass entity,
@@ -2963,6 +2972,25 @@
filterable.addFilter( name, condition );
}
+ private static void parseFetchProfile(Element element, Mappings mappings, String
containingEntityName) {
+ String profileName = element.attributeValue( "name" );
+ FetchProfile profile = mappings.findOrCreateFetchProfile( profileName );
+ Iterator itr = element.elementIterator( "fetch" );
+ while ( itr.hasNext() ) {
+ final Element fetchElement = ( Element ) itr.next();
+ final String association = fetchElement.attributeValue( "association" );
+ final String style = fetchElement.attributeValue( "style" );
+ String entityName = fetchElement.attributeValue( "entity" );
+ if ( entityName == null ) {
+ entityName = containingEntityName;
+ }
+ if ( entityName == null ) {
+ throw new MappingException( "could not determine entity for fetch-profile fetch
[" + profileName + "]:[" + association + "]" );
+ }
+ profile.addFetch( entityName, association, style );
+ }
+ }
+
private static String getSubselect(Element element) {
String subselect = element.attributeValue( "subselect" );
if ( subselect != null ) {
Modified: core/trunk/core/src/main/java/org/hibernate/cfg/Mappings.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/cfg/Mappings.java 2008-08-15 21:03:38 UTC
(rev 15090)
+++ core/trunk/core/src/main/java/org/hibernate/cfg/Mappings.java 2008-08-15 21:20:15 UTC
(rev 15091)
@@ -46,6 +46,7 @@
import org.hibernate.mapping.TypeDef;
import org.hibernate.mapping.AuxiliaryDatabaseObject;
import org.hibernate.mapping.Column;
+import org.hibernate.mapping.FetchProfile;
import org.hibernate.util.StringHelper;
/**
@@ -77,6 +78,7 @@
protected final List propertyReferences;
protected final NamingStrategy namingStrategy;
protected final Map filterDefinitions;
+ protected final Map fetchProfiles;
protected final List auxiliaryDatabaseObjects;
protected final Map extendsQueue;
@@ -111,12 +113,12 @@
final NamingStrategy namingStrategy,
final Map typeDefs,
final Map filterDefinitions,
+ final Map fetchProfiles,
// final List extendsQueue,
final Map extendsQueue,
final List auxiliaryDatabaseObjects,
final Map tableNamebinding,
- final Map columnNameBindingPerTable
- ) {
+ final Map columnNameBindingPerTable) {
this.classes = classes;
this.collections = collections;
this.queries = queries;
@@ -129,6 +131,7 @@
this.namingStrategy = namingStrategy;
this.typeDefs = typeDefs;
this.filterDefinitions = filterDefinitions;
+ this.fetchProfiles = fetchProfiles;
this.extendsQueue = extendsQueue;
this.auxiliaryDatabaseObjects = auxiliaryDatabaseObjects;
this.tableNameBinding = tableNamebinding;
@@ -418,7 +421,20 @@
public FilterDefinition getFilterDefinition(String name) {
return (FilterDefinition) filterDefinitions.get(name);
}
-
+
+ public Map getFetchProfiles() {
+ return fetchProfiles;
+ }
+
+ public FetchProfile findOrCreateFetchProfile(String name) {
+ FetchProfile profile = ( FetchProfile ) fetchProfiles.get( name );
+ if ( profile == null ) {
+ profile = new FetchProfile( name );
+ fetchProfiles.put( name, profile );
+ }
+ return profile;
+ }
+
public boolean isDefaultLazy() {
return defaultLazy;
}
Modified: core/trunk/core/src/main/java/org/hibernate/criterion/SubqueryExpression.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/criterion/SubqueryExpression.java 2008-08-15
21:03:38 UTC (rev 15090)
+++
core/trunk/core/src/main/java/org/hibernate/criterion/SubqueryExpression.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -32,6 +32,7 @@
import org.hibernate.engine.QueryParameters;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.TypedValue;
+import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.impl.CriteriaImpl;
import org.hibernate.loader.criteria.CriteriaJoinWalker;
import org.hibernate.loader.criteria.CriteriaQueryTranslator;
@@ -76,8 +77,9 @@
factory,
criteriaImpl,
criteriaImpl.getEntityOrClassName(),
- new HashMap(),
- innerQuery.getRootSQLALias());
+ LoadQueryInfluencers.NONE,
+ innerQuery.getRootSQLALias()
+ );
String sql = walker.getSQLString();
Added: core/trunk/core/src/main/java/org/hibernate/engine/LoadQueryInfluencers.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/engine/LoadQueryInfluencers.java
(rev 0)
+++
core/trunk/core/src/main/java/org/hibernate/engine/LoadQueryInfluencers.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -0,0 +1,192 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC 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.
+ *
+ * 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.engine;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.Iterator;
+import java.util.HashMap;
+import java.util.HashSet;
+
+import org.hibernate.Filter;
+import org.hibernate.UnknownProfileException;
+import org.hibernate.type.Type;
+import org.hibernate.impl.FilterImpl;
+
+/**
+ * Centralize all options which can influence the SQL query needed to load and
+ * entity. Currently such influencers are defined as:<ul>
+ * <li>filters</li>
+ * <li>fetch profiles</li>
+ * <li>internal fetch profile (merge profile, etc)</li>
+ * </ul>
+ *
+ * @author Steve Ebersole
+ */
+public class LoadQueryInfluencers {
+ /**
+ * Static reference useful for cases where we are creating load SQL
+ * outside the context of any influencers. One such example is
+ * anything created by the session factory.
+ */
+ public static LoadQueryInfluencers NONE = new LoadQueryInfluencers();
+
+ private final SessionFactoryImplementor sessionFactory;
+ private String internalFetchProfile;
+ private Map enabledFilters;
+ private Set enabledFetchProfileNames;
+
+ public LoadQueryInfluencers() {
+ this( null, java.util.Collections.EMPTY_MAP, java.util.Collections.EMPTY_SET );
+ }
+
+ public LoadQueryInfluencers(SessionFactoryImplementor sessionFactory) {
+ this( sessionFactory, new HashMap(), new HashSet() );
+ }
+
+ private LoadQueryInfluencers(SessionFactoryImplementor sessionFactory, Map
enabledFilters, Set enabledFetchProfileNames) {
+ this.sessionFactory = sessionFactory;
+ this.enabledFilters = enabledFilters;
+ this.enabledFetchProfileNames = enabledFetchProfileNames;
+ }
+
+ public SessionFactoryImplementor getSessionFactory() {
+ return sessionFactory;
+ }
+
+
+ // internal fetch profile support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ public String getInternalFetchProfile() {
+ return internalFetchProfile;
+ }
+
+ public void setInternalFetchProfile(String internalFetchProfile) {
+ if ( sessionFactory == null ) {
+ // thats the signal that this is the immutable, context-less
+ // variety
+ throw new IllegalStateException( "Cannot modify context-less
LoadQueryInfluencers" );
+ }
+ this.internalFetchProfile = internalFetchProfile;
+ }
+
+
+ // filter support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ public boolean hasEnabledFilters() {
+ return enabledFilters != null && !enabledFilters.isEmpty();
+ }
+
+ public Map getEnabledFilters() {
+ // First, validate all the enabled filters...
+ //TODO: this implementation has bad performance
+ Iterator itr = enabledFilters.values().iterator();
+ while ( itr.hasNext() ) {
+ final Filter filter = ( Filter ) itr.next();
+ filter.validate();
+ }
+ return enabledFilters;
+ }
+
+ public Filter getEnabledFilter(String filterName) {
+ return ( Filter ) enabledFilters.get( filterName );
+ }
+
+ public Filter enableFilter(String filterName) {
+ FilterImpl filter = new FilterImpl( sessionFactory.getFilterDefinition( filterName )
);
+ enabledFilters.put( filterName, filter );
+ return filter;
+ }
+
+ public void disableFilter(String filterName) {
+ enabledFilters.remove( filterName );
+ }
+
+ public Object getFilterParameterValue(String filterParameterName) {
+ String[] parsed = parseFilterParameterName( filterParameterName );
+ FilterImpl filter = ( FilterImpl ) enabledFilters.get( parsed[0] );
+ if ( filter == null ) {
+ throw new IllegalArgumentException( "Filter [" + parsed[0] + "]
currently not enabled" );
+ }
+ return filter.getParameter( parsed[1] );
+ }
+
+ public Type getFilterParameterType(String filterParameterName) {
+ String[] parsed = parseFilterParameterName( filterParameterName );
+ FilterDefinition filterDef = sessionFactory.getFilterDefinition( parsed[0] );
+ if ( filterDef == null ) {
+ throw new IllegalArgumentException( "Filter [" + parsed[0] + "] not
defined" );
+ }
+ Type type = filterDef.getParameterType( parsed[1] );
+ if ( type == null ) {
+ // this is an internal error of some sort...
+ throw new InternalError( "Unable to locate type for filter parameter" );
+ }
+ return type;
+ }
+
+ public static String[] parseFilterParameterName(String filterParameterName) {
+ int dot = filterParameterName.indexOf( '.' );
+ if ( dot <= 0 ) {
+ throw new IllegalArgumentException( "Invalid filter-parameter name format"
);
+ }
+ String filterName = filterParameterName.substring( 0, dot );
+ String parameterName = filterParameterName.substring( dot + 1 );
+ return new String[] { filterName, parameterName };
+ }
+
+
+ // fetch profile support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ public boolean hasEnabledFetchProfiles() {
+ return enabledFetchProfileNames != null &&
!enabledFetchProfileNames.isEmpty();
+ }
+
+ public Set getEnabledFetchProfileNames() {
+ return enabledFetchProfileNames;
+ }
+
+ private void checkFetchProfileName(String name) {
+ if ( !sessionFactory.containsFetchProfileDefition( name ) ) {
+ throw new UnknownProfileException( name );
+ }
+ }
+
+ public boolean isFetchProfileEnabled(String name) throws UnknownProfileException {
+ checkFetchProfileName( name );
+ return enabledFetchProfileNames.contains( name );
+ }
+
+ public void enableFetchProfile(String name) throws UnknownProfileException {
+ checkFetchProfileName( name );
+ enabledFetchProfileNames.add( name );
+ }
+
+ public void disableFetchProfile(String name) throws UnknownProfileException {
+ checkFetchProfileName( name );
+ enabledFetchProfileNames.remove( name );
+ }
+
+}
Modified:
core/trunk/core/src/main/java/org/hibernate/engine/SessionFactoryImplementor.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/engine/SessionFactoryImplementor.java 2008-08-15
21:03:38 UTC (rev 15090)
+++
core/trunk/core/src/main/java/org/hibernate/engine/SessionFactoryImplementor.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -37,6 +37,7 @@
import org.hibernate.ConnectionReleaseMode;
import org.hibernate.proxy.EntityNotFoundDelegate;
import org.hibernate.engine.query.QueryPlanCache;
+import org.hibernate.engine.profile.FetchProfile;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.cache.QueryCache;
@@ -219,5 +220,13 @@
public EntityNotFoundDelegate getEntityNotFoundDelegate();
public SQLFunctionRegistry getSqlFunctionRegistry();
-
+
+ /**
+ * Retrieve fetch profile by name.
+ *
+ * @param name The name of the profile to retrieve.
+ * @return The profile definition
+ */
+ public FetchProfile getFetchProfile(String name);
+
}
Modified: core/trunk/core/src/main/java/org/hibernate/engine/SessionImplementor.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/engine/SessionImplementor.java 2008-08-15
21:03:38 UTC (rev 15090)
+++ core/trunk/core/src/main/java/org/hibernate/engine/SessionImplementor.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -29,6 +29,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import org.hibernate.CacheMode;
import org.hibernate.EntityMode;
@@ -237,6 +238,7 @@
* @param filterParameterName The filter parameter name in the format
* {FILTER_NAME.PARAMETER_NAME}.
* @return The filter parameter value.
+ * @deprecated use #getLoadQueryInfluencers instead
*/
public Object getFilterParameterValue(String filterParameterName);
@@ -245,6 +247,8 @@
*
* @param filterParameterName The filter parameter name in the format
* {FILTER_NAME.PARAMETER_NAME}.
+ * @return The filter param type
+ * @deprecated use #getLoadQueryInfluencers instead
*/
public Type getFilterParameterType(String filterParameterName);
@@ -253,6 +257,7 @@
* name, with values corresponding to the {@link org.hibernate.impl.FilterImpl}
* instance.
* @return The currently enabled filters.
+ * @deprecated use #getLoadQueryInfluencers instead
*/
public Map getEnabledFilters();
@@ -307,10 +312,22 @@
public void afterScrollOperation();
+ /**
+ * Get the <i>internal</i> fetch profile currently associated with this
session.
+ *
+ * @return The current internal fetch profile, or null if none currently associated.
+ * @deprecated use #getLoadQueryInfluencers instead
+ */
+ public String getFetchProfile();
+
+ /**
+ * Set the current <i>internal</i> fetch profile for this session.
+ *
+ * @param name The internal fetch profile name to use
+ * @deprecated use #getLoadQueryInfluencers instead
+ */
public void setFetchProfile(String name);
- public String getFetchProfile();
-
public JDBCContext getJDBCContext();
/**
@@ -322,4 +339,12 @@
* @return True if the session is closed; false otherwise.
*/
public boolean isClosed();
+
+ /**
+ * Get the load query influencers associated with this session.
+ *
+ * @return the load query influencers associated with this session;
+ * should never be null.
+ */
+ public LoadQueryInfluencers getLoadQueryInfluencers();
}
Added: core/trunk/core/src/main/java/org/hibernate/engine/profile/Association.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/engine/profile/Association.java
(rev 0)
+++ core/trunk/core/src/main/java/org/hibernate/engine/profile/Association.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -0,0 +1,56 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC 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.
+ *
+ * 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.engine.profile;
+
+import org.hibernate.persister.entity.EntityPersister;
+
+/**
+ * Models the association of a given fetch.
+ *
+ * @author Steve Ebersole
+ */
+public class Association {
+ private final EntityPersister owner;
+ private final String associationPath;
+ private final String role;
+
+ public Association(EntityPersister owner, String associationPath) {
+ this.owner = owner;
+ this.associationPath = associationPath;
+ this.role = owner.getEntityName() + '.' + associationPath;
+ }
+
+ public EntityPersister getOwner() {
+ return owner;
+ }
+
+ public String getAssociationPath() {
+ return associationPath;
+ }
+
+ public String getRole() {
+ return role;
+ }
+}
Added: core/trunk/core/src/main/java/org/hibernate/engine/profile/Fetch.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/engine/profile/Fetch.java
(rev 0)
+++ core/trunk/core/src/main/java/org/hibernate/engine/profile/Fetch.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -0,0 +1,84 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC 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.
+ *
+ * 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.engine.profile;
+
+/**
+ * Models an individual fetch within a profile.
+ *
+ * @author Steve Ebersole
+ */
+public class Fetch {
+ private final Association association;
+ private final Style style;
+
+ public Fetch(Association association, Style style) {
+ this.association = association;
+ this.style = style;
+ }
+
+ public Association getAssociation() {
+ return association;
+ }
+
+ public Style getStyle() {
+ return style;
+ }
+
+ /**
+ * The type or style of fetch. For the moment we limit this to
+ * join and select, though technically subselect would be valid
+ * here as as well; however, to support subselect here would
+ * require major changes to the subselect loading code (which is
+ * needed for other things as well anyway).
+ */
+ public static class Style {
+ public static final Style JOIN = new Style( "join" );
+ public static final Style SELECT = new Style( "select" );
+
+ private final String name;
+
+ private Style(String name) {
+ this.name = name;
+ }
+
+ public String toString() {
+ return name;
+ }
+
+ public static Style parse(String name) {
+ if ( SELECT.name.equals( name ) ) {
+ return SELECT;
+ }
+ else {
+ // the default...
+ return JOIN;
+ }
+ }
+ }
+
+ public String toString() {
+ return "Fetch[" + style + "{" + association.getRole() +
"}]";
+ }
+}
Added: core/trunk/core/src/main/java/org/hibernate/engine/profile/FetchProfile.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/engine/profile/FetchProfile.java
(rev 0)
+++
core/trunk/core/src/main/java/org/hibernate/engine/profile/FetchProfile.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -0,0 +1,169 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC 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.
+ *
+ * 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.engine.profile;
+
+import java.util.Map;
+import java.util.HashMap;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.type.Type;
+import org.hibernate.type.BagType;
+import org.hibernate.type.AssociationType;
+
+/**
+ * A 'fetch profile' allows a user to dynamically modify the fetching
+ * strategy used for particular associations at runtime, whereas that
+ * information was historically only statically defined in the metadata.
+ *
+ * @author Steve Ebersole
+ */
+public class FetchProfile {
+ private static final Logger log = LoggerFactory.getLogger( FetchProfile.class );
+
+ private final String name;
+ private Map fetches = new HashMap();
+
+ private boolean containsJoinFetchedCollection = false;
+ private boolean containsJoinFetchedBag = false;
+ private Fetch bagJoinFetch;
+
+ /**
+ * A 'fetch profile' is uniquely named within a
+ * {@link SessionFactoryImplementor SessionFactory}, thus it is also
+ * uniquely and easily identifiable within that
+ * {@link SessionFactoryImplementor SessionFactory}.
+ *
+ * @param name The name under which we are bound in the sessionFactory
+ */
+ public FetchProfile(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Add a fetch to the profile.
+ *
+ * @param association The association to be fetched
+ * @param fetchStyleName The name of the fetch style to apply
+ */
+ public void addFetch(Association association, String fetchStyleName) {
+ addFetch( association, Fetch.Style.parse( fetchStyleName ) );
+ }
+
+ /**
+ * Add a fetch to the profile.
+ *
+ * @param association The association to be fetched
+ * @param style The style to apply
+ */
+ public void addFetch(Association association, Fetch.Style style) {
+ addFetch( new Fetch( association, style ) );
+ }
+
+ /**
+ * Add a fetch to the profile.
+ *
+ * @param fetch The fetch to add.
+ */
+ public void addFetch(Fetch fetch) {
+ Type associationType = fetch.getAssociation().getOwner().getPropertyType(
fetch.getAssociation().getAssociationPath() );
+ if ( associationType.isCollectionType() ) {
+ log.trace( "handling request to add collection fetch [{}]",
fetch.getAssociation().getRole() );
+
+ // couple of things for whcih to account in the case of collection
+ // join fetches
+ if ( Fetch.Style.JOIN == fetch.getStyle() ) {
+ // first, if this is a bag we need to ignore it if we previously
+ // processed collection join fetches
+ if ( BagType.class.isInstance( associationType ) ) {
+ if ( containsJoinFetchedCollection ) {
+ log.warn( "Ignoring bag join fetch [{}] due to prior collection join
fetch", fetch.getAssociation().getRole() );
+ return; // EARLY EXIT!!!
+ }
+ }
+
+ // also, in cases where we are asked to add a collection join
+ // fetch where we had already added a bag join fetch previously,
+ // we need to go back and ignore that previous bag join fetch.
+ if ( containsJoinFetchedBag ) {
+ if ( fetches.remove( bagJoinFetch.getAssociation().getRole() ) != bagJoinFetch ) {
+ // just for safety...
+ log.warn( "Unable to erase previously added bag join fetch" );
+ }
+ bagJoinFetch = null;
+ containsJoinFetchedBag = false;
+ }
+
+ containsJoinFetchedCollection = true;
+ }
+ }
+ fetches.put( fetch.getAssociation().getRole(), fetch );
+ }
+
+ /**
+ * Getter for property 'name'.
+ *
+ * @return Value for property 'name'.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Getter for property 'fetches'. Map of {@link Fetch} instances,
+ * keyed by associaion <tt>role</tt>
+ *
+ * @return Value for property 'fetches'.
+ */
+ public Map getFetches() {
+ return fetches;
+ }
+
+ public Fetch getFetchByRole(String role) {
+ return ( Fetch ) fetches.get( role );
+ }
+
+ /**
+ * Getter for property 'containsJoinFetchedCollection', which flags whether
+ * this fetch profile contained any collection join fetches.
+ *
+ * @return Value for property 'containsJoinFetchedCollection'.
+ */
+ public boolean isContainsJoinFetchedCollection() {
+ return containsJoinFetchedCollection;
+ }
+
+ /**
+ * Getter for property 'containsJoinFetchedBag', which flags whether this
+ * fetch profile contained any bag join fetches
+ *
+ * @return Value for property 'containsJoinFetchedBag'.
+ */
+ public boolean isContainsJoinFetchedBag() {
+ return containsJoinFetchedBag;
+ }
+}
Modified: core/trunk/core/src/main/java/org/hibernate/impl/SessionFactoryImpl.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/impl/SessionFactoryImpl.java 2008-08-15
21:03:38 UTC (rev 15090)
+++ core/trunk/core/src/main/java/org/hibernate/impl/SessionFactoryImpl.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -84,6 +84,9 @@
import org.hibernate.engine.NamedSQLQueryDefinition;
import org.hibernate.engine.ResultSetMappingDefinition;
import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.engine.profile.FetchProfile;
+import org.hibernate.engine.profile.Fetch;
+import org.hibernate.engine.profile.Association;
import org.hibernate.engine.query.QueryPlanCache;
import org.hibernate.engine.query.sql.NativeSQLQuerySpecification;
import org.hibernate.event.EventListeners;
@@ -100,6 +103,7 @@
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Queryable;
+import org.hibernate.persister.entity.Loadable;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.proxy.EntityNotFoundDelegate;
import org.hibernate.stat.Statistics;
@@ -156,6 +160,7 @@
private final transient Map namedSqlQueries;
private final transient Map sqlResultSetMappings;
private final transient Map filters;
+ private final transient Map fetchProfiles;
private final transient Map imports;
private final transient Interceptor interceptor;
private final transient Settings settings;
@@ -198,6 +203,7 @@
public void sessionFactoryClosed(SessionFactory factory) {
}
};
+
this.filters = new HashMap();
this.filters.putAll( cfg.getFilterDefinitions() );
@@ -412,6 +418,43 @@
}
this.entityNotFoundDelegate = entityNotFoundDelegate;
+ // this needs to happen after persisters are all ready to go...
+ this.fetchProfiles = new HashMap();
+ itr = cfg.getFetchProfiles().values().iterator();
+ while ( itr.hasNext() ) {
+ final org.hibernate.mapping.FetchProfile mappingProfile =
+ ( org.hibernate.mapping.FetchProfile ) itr.next();
+ final FetchProfile fetchProfile = new FetchProfile( mappingProfile.getName() );
+ Iterator fetches = mappingProfile.getFetches().iterator();
+ while ( fetches.hasNext() ) {
+ final org.hibernate.mapping.FetchProfile.Fetch mappingFetch =
+ ( org.hibernate.mapping.FetchProfile.Fetch ) fetches.next();
+ // resolve the persister owning the fetch
+ final String entityName = getImportedClassName( mappingFetch.getEntity() );
+ final EntityPersister owner = ( EntityPersister ) ( entityName == null ? null :
entityPersisters.get( entityName ) );
+ if ( owner == null ) {
+ throw new HibernateException(
+ "Unable to resolve entity reference [" + mappingFetch.getEntity()
+ + "] in fetch profile [" + fetchProfile.getName() + "]"
+ );
+ }
+
+ // validate the specified association fetch
+ Type associationType = owner.getPropertyType( mappingFetch.getAssociation() );
+ if ( associationType == null || !associationType.isAssociationType() ) {
+ throw new HibernateException( "Fetch profile [" + fetchProfile.getName() +
"] specified an invalid association" );
+ }
+
+ // resolve the style
+ final Fetch.Style fetchStyle = Fetch.Style.parse( mappingFetch.getStyle() );
+
+ // then construct the fetch instance...
+ fetchProfile.addFetch( new Association( owner, mappingFetch.getAssociation() ),
fetchStyle );
+ ( ( Loadable ) owner ).registerAffectingFetchProfile( fetchProfile.getName() );
+ }
+ fetchProfiles.put( fetchProfile.getName(), fetchProfile );
+ }
+
this.observer.sessionFactoryCreated( this );
}
@@ -1004,6 +1047,10 @@
return def;
}
+ public boolean containsFetchProfileDefition(String name) {
+ return fetchProfiles.containsKey( name );
+ }
+
public Set getDefinedFilterNames() {
return filters.keySet();
}
@@ -1061,6 +1108,14 @@
return entityNotFoundDelegate;
}
+ public SQLFunctionRegistry getSqlFunctionRegistry() {
+ return sqlFunctionRegistry;
+ }
+
+ public FetchProfile getFetchProfile(String name) {
+ return ( FetchProfile ) fetchProfiles.get( name );
+ }
+
/**
* Custom serialization hook used during Session serialization.
*
@@ -1102,8 +1157,4 @@
}
return ( SessionFactoryImpl ) result;
}
-
- public SQLFunctionRegistry getSqlFunctionRegistry() {
- return sqlFunctionRegistry;
- }
}
Modified: core/trunk/core/src/main/java/org/hibernate/impl/SessionImpl.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/impl/SessionImpl.java 2008-08-15 21:03:38
UTC (rev 15090)
+++ core/trunk/core/src/main/java/org/hibernate/impl/SessionImpl.java 2008-08-15 21:20:15
UTC (rev 15091)
@@ -66,6 +66,7 @@
import org.hibernate.Transaction;
import org.hibernate.TransientObjectException;
import org.hibernate.UnresolvableObjectException;
+import org.hibernate.UnknownProfileException;
import org.hibernate.collection.PersistentCollection;
import org.hibernate.engine.ActionQueue;
import org.hibernate.engine.CollectionEntry;
@@ -76,6 +77,7 @@
import org.hibernate.engine.QueryParameters;
import org.hibernate.engine.StatefulPersistenceContext;
import org.hibernate.engine.Status;
+import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.engine.query.FilterQueryPlan;
import org.hibernate.engine.query.HQLQueryPlan;
import org.hibernate.engine.query.NativeSQLQueryPlan;
@@ -167,10 +169,8 @@
private transient boolean flushBeforeCompletionEnabled;
private transient boolean autoCloseSessionEnabled;
private transient ConnectionReleaseMode connectionReleaseMode;
-
- private transient String fetchProfile;
- private transient Map enabledFilters = new HashMap();
+ private transient LoadQueryInfluencers loadQueryInfluencers;
private transient Session rootSession;
private transient Map childSessionsByEntityMode;
@@ -195,6 +195,8 @@
this.autoCloseSessionEnabled = false;
this.connectionReleaseMode = null;
+ loadQueryInfluencers = new LoadQueryInfluencers( factory );
+
if ( factory.getStatistics().isStatisticsEnabled() ) {
factory.getStatisticsImplementor().openSession();
}
@@ -239,6 +241,8 @@
this.connectionReleaseMode = connectionReleaseMode;
this.jdbcContext = new JDBCContext( this, connection, interceptor );
+ loadQueryInfluencers = new LoadQueryInfluencers( factory );
+
if ( factory.getStatistics().isStatisticsEnabled() ) {
factory.getStatisticsImplementor().openSession();
}
@@ -1048,76 +1052,7 @@
flush();
}
- public Filter getEnabledFilter(String filterName) {
- checkTransactionSynchStatus();
- return (Filter) enabledFilters.get(filterName);
- }
- public Filter enableFilter(String filterName) {
- errorIfClosed();
- checkTransactionSynchStatus();
- FilterImpl filter = new FilterImpl( factory.getFilterDefinition(filterName) );
- enabledFilters.put(filterName, filter);
- return filter;
- }
-
- public void disableFilter(String filterName) {
- errorIfClosed();
- checkTransactionSynchStatus();
- enabledFilters.remove(filterName);
- }
-
- public Object getFilterParameterValue(String filterParameterName) {
- errorIfClosed();
- checkTransactionSynchStatus();
- String[] parsed = parseFilterParameterName(filterParameterName);
- FilterImpl filter = (FilterImpl) enabledFilters.get( parsed[0] );
- if (filter == null) {
- throw new IllegalArgumentException("Filter [" + parsed[0] + "]
currently not enabled");
- }
- return filter.getParameter( parsed[1] );
- }
-
- public Type getFilterParameterType(String filterParameterName) {
- errorIfClosed();
- checkTransactionSynchStatus();
- String[] parsed = parseFilterParameterName(filterParameterName);
- FilterDefinition filterDef = factory.getFilterDefinition( parsed[0] );
- if (filterDef == null) {
- throw new IllegalArgumentException("Filter [" + parsed[0] + "] not
defined");
- }
- Type type = filterDef.getParameterType( parsed[1] );
- if (type == null) {
- // this is an internal error of some sort...
- throw new InternalError("Unable to locate type for filter parameter");
- }
- return type;
- }
-
- public Map getEnabledFilters() {
- errorIfClosed();
- checkTransactionSynchStatus();
- // First, validate all the enabled filters...
- //TODO: this implementation has bad performance
- Iterator itr = enabledFilters.values().iterator();
- while ( itr.hasNext() ) {
- final Filter filter = (Filter) itr.next();
- filter.validate();
- }
- return enabledFilters;
- }
-
- private String[] parseFilterParameterName(String filterParameterName) {
- int dot = filterParameterName.indexOf('.');
- if (dot <= 0) {
- throw new IllegalArgumentException("Invalid filter-parameter name format");
// TODO: what type?
- }
- String filterName = filterParameterName.substring(0, dot);
- String parameterName = filterParameterName.substring(dot+1);
- return new String[] {filterName, parameterName};
- }
-
-
/**
* Retrieve a list of persistent objects using a hibernate query
*/
@@ -1432,7 +1367,7 @@
return listFilter( collection, filter, new QueryParameters( new Type[]{null, type}, new
Object[]{null, value} ) );
}
- public Collection filter(Object collection, String filter, Object[] values, Type[]
types)
+ public Collection filter(Object collection, String filter, Object[] values, Type[]
types)
throws HibernateException {
Object[] vals = new Object[values.length + 1];
Type[] typs = new Type[types.length + 1];
@@ -1491,7 +1426,7 @@
return plan;
}
- public List listFilter(Object collection, String filter, QueryParameters
queryParameters)
+ public List listFilter(Object collection, String filter, QueryParameters
queryParameters)
throws HibernateException {
errorIfClosed();
checkTransactionSynchStatus();
@@ -1511,7 +1446,7 @@
return results;
}
- public Iterator iterateFilter(Object collection, String filter, QueryParameters
queryParameters)
+ public Iterator iterateFilter(Object collection, String filter, QueryParameters
queryParameters)
throws HibernateException {
errorIfClosed();
checkTransactionSynchStatus();
@@ -1552,7 +1487,7 @@
factory,
criteria,
entityName,
- getEnabledFilters()
+ getLoadQueryInfluencers()
);
autoFlushIfRequired( loader.getQuerySpaces() );
dontFlushFromFind++;
@@ -1579,7 +1514,7 @@
factory,
criteria,
implementors[i],
- getEnabledFilters()
+ getLoadQueryInfluencers()
);
spaces.addAll( loaders[i].getQuerySpaces() );
@@ -1680,7 +1615,7 @@
);
}
- public ScrollableResults scrollCustomQuery(CustomQuery customQuery, QueryParameters
queryParameters)
+ public ScrollableResults scrollCustomQuery(CustomQuery customQuery, QueryParameters
queryParameters)
throws HibernateException {
errorIfClosed();
checkTransactionSynchStatus();
@@ -1734,7 +1669,7 @@
return factory;
}
- public void initializeCollection(PersistentCollection collection, boolean writing)
+ public void initializeCollection(PersistentCollection collection, boolean writing)
throws HibernateException {
errorIfClosed();
checkTransactionSynchStatus();
@@ -1882,23 +1817,107 @@
// nothing to do in a stateful session
}
- public String getFetchProfile() {
+ public JDBCContext getJDBCContext() {
+ errorIfClosed();
checkTransactionSynchStatus();
- return fetchProfile;
+ return jdbcContext;
}
- public JDBCContext getJDBCContext() {
+ public LoadQueryInfluencers getLoadQueryInfluencers() {
+ return loadQueryInfluencers;
+ }
+
+ // filter support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ /**
+ * {@inheritDoc}
+ */
+ public Filter getEnabledFilter(String filterName) {
+ checkTransactionSynchStatus();
+ return loadQueryInfluencers.getEnabledFilter( filterName );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Filter enableFilter(String filterName) {
errorIfClosed();
checkTransactionSynchStatus();
- return jdbcContext;
+ return loadQueryInfluencers.enableFilter( filterName );
}
+ /**
+ * {@inheritDoc}
+ */
+ public void disableFilter(String filterName) {
+ errorIfClosed();
+ checkTransactionSynchStatus();
+ loadQueryInfluencers.disableFilter( filterName );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object getFilterParameterValue(String filterParameterName) {
+ errorIfClosed();
+ checkTransactionSynchStatus();
+ return loadQueryInfluencers.getFilterParameterValue( filterParameterName );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Type getFilterParameterType(String filterParameterName) {
+ errorIfClosed();
+ checkTransactionSynchStatus();
+ return loadQueryInfluencers.getFilterParameterType( filterParameterName );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Map getEnabledFilters() {
+ errorIfClosed();
+ checkTransactionSynchStatus();
+ return loadQueryInfluencers.getEnabledFilters();
+ }
+
+
+ // internal fetch profile support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getFetchProfile() {
+ checkTransactionSynchStatus();
+ return loadQueryInfluencers.getInternalFetchProfile();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public void setFetchProfile(String fetchProfile) {
errorIfClosed();
checkTransactionSynchStatus();
- this.fetchProfile = fetchProfile;
+ loadQueryInfluencers.setInternalFetchProfile( fetchProfile );
}
+
+ // fetch profile support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ public boolean isFetchProfileEnabled(String name) throws UnknownProfileException {
+ return loadQueryInfluencers.isFetchProfileEnabled( name );
+ }
+
+ public void enableFetchProfile(String name) throws UnknownProfileException {
+ loadQueryInfluencers.enableFetchProfile( name );
+ }
+
+ public void disableFetchProfile(String name) throws UnknownProfileException {
+ loadQueryInfluencers.disableFetchProfile( name );
+ }
+
+
private void checkTransactionSynchStatus() {
if ( jdbcContext != null && !isClosed() ) {
jdbcContext.registerSynchronizationIfPossible();
@@ -1923,7 +1942,6 @@
cacheMode = CacheMode.parse( ( String ) ois.readObject() );
flushBeforeCompletionEnabled = ois.readBoolean();
autoCloseSessionEnabled = ois.readBoolean();
- fetchProfile = ( String ) ois.readObject();
interceptor = ( Interceptor ) ois.readObject();
factory = SessionFactoryImpl.deserialize( ois );
@@ -1936,12 +1954,13 @@
persistenceContext = StatefulPersistenceContext.deserialize( ois, this );
actionQueue = ActionQueue.deserialize( ois, this );
- enabledFilters = ( Map ) ois.readObject();
+ loadQueryInfluencers = ( LoadQueryInfluencers ) ois.readObject();
+
childSessionsByEntityMode = ( Map ) ois.readObject();
- Iterator iter = enabledFilters.values().iterator();
+ Iterator iter = loadQueryInfluencers.getEnabledFilters().values().iterator();
while ( iter.hasNext() ) {
- ( ( FilterImpl ) iter.next() ).afterDeserialize(factory);
+ ( ( FilterImpl ) iter.next() ).afterDeserialize( factory );
}
if ( isRootSession && childSessionsByEntityMode != null ) {
@@ -1975,7 +1994,6 @@
oos.writeObject( cacheMode.toString() );
oos.writeBoolean( flushBeforeCompletionEnabled );
oos.writeBoolean( autoCloseSessionEnabled );
- oos.writeObject( fetchProfile );
// we need to writeObject() on this since interceptor is user defined
oos.writeObject( interceptor );
@@ -1989,7 +2007,7 @@
actionQueue.serialize( oos );
// todo : look at optimizing these...
- oos.writeObject( enabledFilters );
+ oos.writeObject( loadQueryInfluencers );
oos.writeObject( childSessionsByEntityMode );
}
}
Modified: core/trunk/core/src/main/java/org/hibernate/impl/StatelessSessionImpl.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/impl/StatelessSessionImpl.java 2008-08-15
21:03:38 UTC (rev 15090)
+++ core/trunk/core/src/main/java/org/hibernate/impl/StatelessSessionImpl.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -57,6 +57,7 @@
import org.hibernate.engine.QueryParameters;
import org.hibernate.engine.StatefulPersistenceContext;
import org.hibernate.engine.Versioning;
+import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.engine.query.HQLQueryPlan;
import org.hibernate.engine.query.NativeSQLQueryPlan;
import org.hibernate.engine.query.sql.NativeSQLQuerySpecification;
@@ -527,12 +528,12 @@
errorIfClosed();
String entityName = criteria.getEntityOrClassName();
CriteriaLoader loader = new CriteriaLoader(
- getOuterJoinLoadable(entityName),
+ getOuterJoinLoadable( entityName ),
factory,
criteria,
entityName,
- getEnabledFilters()
- );
+ getLoadQueryInfluencers()
+ );
return loader.scroll(this, scrollMode);
}
@@ -548,7 +549,7 @@
factory,
criteria,
implementors[i],
- getEnabledFilters()
+ getLoadQueryInfluencers()
);
}
@@ -623,6 +624,10 @@
return jdbcContext;
}
+ public LoadQueryInfluencers getLoadQueryInfluencers() {
+ return null;
+ }
+
public void setFetchProfile(String name) {}
public void afterTransactionBegin(Transaction tx) {}
Modified:
core/trunk/core/src/main/java/org/hibernate/loader/AbstractEntityJoinWalker.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/loader/AbstractEntityJoinWalker.java 2008-08-15
21:03:38 UTC (rev 15090)
+++
core/trunk/core/src/main/java/org/hibernate/loader/AbstractEntityJoinWalker.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -26,13 +26,16 @@
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
+import java.util.Iterator;
import org.hibernate.FetchMode;
import org.hibernate.LockMode;
import org.hibernate.MappingException;
import org.hibernate.engine.CascadeStyle;
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.entity.Loadable;
import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.sql.JoinFragment;
@@ -51,55 +54,60 @@
private final OuterJoinLoadable persister;
private final String alias;
- public AbstractEntityJoinWalker(OuterJoinLoadable persister, SessionFactoryImplementor
factory, Map enabledFilters) {
- this( persister, factory, enabledFilters, null );
+ public AbstractEntityJoinWalker(
+ OuterJoinLoadable persister,
+ SessionFactoryImplementor factory,
+ LoadQueryInfluencers loadQueryInfluencers) {
+ this( persister, factory, loadQueryInfluencers, null );
}
- public AbstractEntityJoinWalker(OuterJoinLoadable persister, SessionFactoryImplementor
factory, Map enabledFilters, String alias) {
- super( factory, enabledFilters );
+ public AbstractEntityJoinWalker(
+ OuterJoinLoadable persister,
+ SessionFactoryImplementor factory,
+ LoadQueryInfluencers loadQueryInfluencers,
+ String alias) {
+ super( factory, loadQueryInfluencers );
this.persister = persister;
this.alias = ( alias == null ) ? generateRootAlias( persister.getEntityName() ) :
alias;
}
protected final void initAll(
- final String whereString,
- final String orderByString,
- final LockMode lockMode)
- throws MappingException {
+ final String whereString,
+ final String orderByString,
+ final LockMode lockMode) 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,
- getFactory(),
- CollectionHelper.EMPTY_MAP
- ) );
-
+ allAssociations.add(
+ new OuterJoinableAssociation(
+ persister.getEntityType(),
+ null,
+ null,
+ alias,
+ JoinFragment.LEFT_OUTER_JOIN,
+ getFactory(),
+ CollectionHelper.EMPTY_MAP
+ )
+ );
initPersisters(allAssociations, lockMode);
initStatementString( whereString, orderByString, lockMode);
}
protected final void initProjection(
- final String projectionString,
- final String whereString,
- final String orderByString,
- final String groupByString,
- final LockMode lockMode)
- throws MappingException {
+ final String projectionString,
+ final String whereString,
+ final String orderByString,
+ final String groupByString,
+ final LockMode lockMode) throws MappingException {
walkEntityTree( persister, getAlias() );
persisters = new Loadable[0];
initStatementString(projectionString, whereString, orderByString, groupByString,
lockMode);
}
private void initStatementString(
- final String condition,
- final String orderBy,
- final LockMode lockMode)
- throws MappingException {
+ final String condition,
+ final String orderBy,
+ final LockMode lockMode) throws MappingException {
initStatementString(null, condition, orderBy, "", lockMode);
}
@@ -149,9 +157,35 @@
* The superclass deliberately excludes collections
*/
protected boolean isJoinedFetchEnabled(AssociationType type, FetchMode config,
CascadeStyle cascadeStyle) {
- return isJoinedFetchEnabledInMapping(config, type);
+ return isJoinedFetchEnabledInMapping( config, type );
}
+ protected final boolean isJoinFetchEnabledByProfile(OuterJoinLoadable persister, String
path, int propertyNumber) {
+ if ( !getLoadQueryInfluencers().hasEnabledFetchProfiles() ) {
+ // perf optimization
+ return false;
+ }
+
+ // ugh, this stuff has to be made easier...
+ String rootPropertyName = persister.getSubclassPropertyName( propertyNumber );
+ int pos = path.lastIndexOf( rootPropertyName );
+ String relativePropertyPath = pos >= 0
+ ? path.substring( pos )
+ : rootPropertyName;
+ String fetchRole = persister.getEntityName() + "." + relativePropertyPath;
+
+ Iterator profiles =
getLoadQueryInfluencers().getEnabledFetchProfileNames().iterator();
+ while ( profiles.hasNext() ) {
+ final String profileName = ( String ) profiles.next();
+ final FetchProfile profile = getFactory().getFetchProfile( profileName );
+ final Fetch fetch = profile.getFetchByRole( fetchRole );
+ if ( fetch != null && Fetch.Style.JOIN == fetch.getStyle() ) {
+ return true;
+ }
+ }
+ return false;
+ }
+
public abstract String getComment();
protected final Loadable getPersister() {
Modified: core/trunk/core/src/main/java/org/hibernate/loader/JoinWalker.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/loader/JoinWalker.java 2008-08-15 21:03:38
UTC (rev 15090)
+++ core/trunk/core/src/main/java/org/hibernate/loader/JoinWalker.java 2008-08-15 21:20:15
UTC (rev 15091)
@@ -29,7 +29,6 @@
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
-import java.util.Map;
import java.util.Set;
import org.hibernate.FetchMode;
@@ -39,6 +38,9 @@
import org.hibernate.engine.CascadeStyle;
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;
@@ -69,7 +71,7 @@
private final SessionFactoryImplementor factory;
protected final List associations = new ArrayList();
private final Set visitedAssociationKeys = new HashSet();
- private final Map enabledFilters;
+ private final LoadQueryInfluencers loadQueryInfluencers;
protected String[] suffixes;
protected String[] collectionSuffixes;
@@ -81,6 +83,14 @@
protected String[] aliases;
protected LockMode[] lockModeArray;
protected String sql;
+
+ protected JoinWalker(
+ SessionFactoryImplementor factory,
+ LoadQueryInfluencers loadQueryInfluencers) {
+ this.factory = factory;
+ this.loadQueryInfluencers = loadQueryInfluencers;
+
+ }
public String[] getCollectionSuffixes() {
return collectionSuffixes;
@@ -169,14 +179,9 @@
protected Dialect getDialect() {
return factory.getDialect();
}
-
- protected Map getEnabledFilters() {
- return enabledFilters;
- }
- protected JoinWalker(SessionFactoryImplementor factory, Map enabledFilters) {
- this.factory = factory;
- this.enabledFilters = enabledFilters;
+ public LoadQueryInfluencers getLoadQueryInfluencers() {
+ return loadQueryInfluencers;
}
/**
@@ -184,15 +189,13 @@
* of associations to be fetched by outerjoin (if necessary)
*/
private void addAssociationToJoinTreeIfNecessary(
- final AssociationType type,
- final String[] aliasedLhsColumns,
- final String alias,
- final String path,
- int currentDepth,
- final int joinType)
- throws MappingException {
-
- if (joinType>=0) {
+ final AssociationType type,
+ final String[] aliasedLhsColumns,
+ final String alias,
+ final String path,
+ int currentDepth,
+ final int joinType) throws MappingException {
+ if ( joinType >= 0 ) {
addAssociationToJoinTree(
type,
aliasedLhsColumns,
@@ -200,9 +203,8 @@
path,
currentDepth,
joinType
- );
+ );
}
-
}
/**
@@ -210,35 +212,37 @@
* of associations to be fetched by outerjoin
*/
private void addAssociationToJoinTree(
- final AssociationType type,
- final String[] aliasedLhsColumns,
- final String alias,
- final String path,
- final int currentDepth,
- final int joinType)
- throws MappingException {
+ final AssociationType type,
+ final String[] aliasedLhsColumns,
+ final String alias,
+ String path,
+ final int currentDepth,
+ final int joinType) throws MappingException {
Joinable joinable = type.getAssociatedJoinable( getFactory() );
- String subalias = generateTableAlias(
- associations.size()+1, //before adding to collection!
- path,
- joinable
- );
+ // important to generate alias based on size of association collection
+ // *before* adding this join to that collection
+ String subalias = generateTableAlias( associations.size() + 1, path, joinable );
+ // NOTE : it should be fine to continue to pass only filters below
+ // (instead of LoadQueryInfluencers) since "from that point on" we
+ // only need to worry about restrictions (and not say adding more
+ // joins)
OuterJoinableAssociation assoc = new OuterJoinableAssociation(
type,
alias,
aliasedLhsColumns,
subalias,
joinType,
- getFactory(),
- enabledFilters
- );
- assoc.validateJoin(path);
- associations.add(assoc);
+ getFactory(),
+ loadQueryInfluencers.getEnabledFilters()
+ );
+ assoc.validateJoin( path );
+ associations.add( assoc );
- int nextDepth = currentDepth+1;
+ int nextDepth = currentDepth + 1;
+// path = "";
if ( !joinable.isCollection() ) {
if (joinable instanceof OuterJoinLoadable) {
walkEntityTree(
@@ -263,11 +267,19 @@
}
/**
- * For an entity class, return a list of associations to be fetched by outerjoin
+ * 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)}.
+ *
+ * @param persister The persister representing the entity to be walked.
+ * @param alias The (root) alias to use for this entity/persister.
+ * @throws org.hibernate.MappingException ???
*/
- protected final void walkEntityTree(OuterJoinLoadable persister, String alias)
- throws MappingException {
- walkEntityTree(persister, alias, "", 0);
+ protected final void walkEntityTree(
+ OuterJoinLoadable persister,
+ String alias) throws MappingException {
+ walkEntityTree( persister, alias, "", 0 );
}
/**
@@ -344,38 +356,49 @@
}
/**
- * Walk the tree for a particular entity association
+ * Process a particular association owned by the entity
+ *
+ * @param associationType The type representing the association to be
+ * processed.
+ * @param persister The owner of the association to be processed.
+ * @param propertyNumber The property number for the association
+ * (relative to the persister).
+ * @param alias The entity alias
+ * @param path The path to the association
+ * @param nullable is the association nullable (which I think is supposed
+ * to indicate inner/outer join semantics).
+ * @param currentDepth The current join depth
+ * @throws org.hibernate.MappingException ???
*/
- private final void walkEntityAssociationTree(
- final AssociationType associationType,
- final OuterJoinLoadable persister,
- final int propertyNumber,
- final String alias,
- final String path,
- final boolean nullable,
- final int currentDepth)
- throws MappingException {
-
+ private void walkEntityAssociationTree(
+ final AssociationType associationType,
+ final OuterJoinLoadable persister,
+ final int propertyNumber,
+ final String alias,
+ final String path,
+ final boolean nullable,
+ final int currentDepth) throws MappingException {
String[] aliasedLhsColumns = JoinHelper.getAliasedLHSColumnNames(
associationType, alias, propertyNumber, persister, getFactory()
- );
-
+ );
String[] lhsColumns = JoinHelper.getLHSColumnNames(
associationType, propertyNumber, persister, getFactory()
- );
+ );
String lhsTable = JoinHelper.getLHSTableName(associationType, propertyNumber,
persister);
String subpath = subPath( path, persister.getSubclassPropertyName(propertyNumber) );
int joinType = getJoinType(
+ persister,
+ subpath,
+ propertyNumber,
associationType,
- persister.getFetchMode(propertyNumber),
- subpath,
+ persister.getFetchMode( propertyNumber ),
+ persister.getCascadeStyle( propertyNumber ),
lhsTable,
lhsColumns,
nullable,
- currentDepth,
- persister.getCascadeStyle(propertyNumber)
- );
+ currentDepth
+ );
addAssociationToJoinTreeIfNecessary(
associationType,
aliasedLhsColumns,
@@ -383,27 +406,110 @@
subpath,
currentDepth,
joinType
- );
+ );
+ }
+ /**
+ * Determine the appropriate type of join (if any) to use to fetch the
+ * given association.
+ *
+ * @param persister The owner of the association.
+ * @param path The path to the association
+ * @param propertyNumber The property number representing the association.
+ * @param associationType The association type.
+ * @param metadataFetchMode The metadata-defined fetch mode.
+ * @param metadataCascadeStyle The metadata-defined cascade style.
+ * @param lhsTable The owner table
+ * @param lhsColumns The owner join columns
+ * @param nullable Is the association nullable.
+ * @param currentDepth Current join depth
+ * @return type of join to use ({@link JoinFragment#INNER_JOIN},
+ * {@link JoinFragment#LEFT_OUTER_JOIN}, or -1 to indicate no joining.
+ * @throws MappingException ??
+ */
+ protected int getJoinType(
+ OuterJoinLoadable persister,
+ final String path,
+ int propertyNumber,
+ AssociationType associationType,
+ FetchMode metadataFetchMode,
+ CascadeStyle metadataCascadeStyle,
+ String lhsTable,
+ String[] lhsColumns,
+ final boolean nullable,
+ final int currentDepth) throws MappingException {
+ return getJoinType(
+ associationType,
+ metadataFetchMode,
+ path,
+ lhsTable,
+ lhsColumns,
+ nullable,
+ currentDepth,
+ metadataCascadeStyle
+ );
}
/**
- * For an entity class, add to a list of associations to be fetched
- * by outerjoin
+ * Determine the appropriate associationType of join (if any) to use to fetch the
+ * given association.
+ *
+ * @param associationType The association associationType.
+ * @param config The metadata-defined fetch mode.
+ * @param path The path to the association
+ * @param lhsTable The owner table
+ * @param lhsColumns The owner join columns
+ * @param nullable Is the association nullable.
+ * @param currentDepth Current join depth
+ * @param cascadeStyle The metadata-defined cascade style.
+ * @return type of join to use ({@link JoinFragment#INNER_JOIN},
+ * {@link JoinFragment#LEFT_OUTER_JOIN}, or -1 to indicate no joining.
+ * @throws MappingException ??
*/
- private final void walkEntityTree(
- final OuterJoinLoadable persister,
- final String alias,
- final String path,
- final int currentDepth)
- throws MappingException {
+ private int getJoinType(
+ AssociationType associationType,
+ FetchMode config,
+ String path,
+ String lhsTable,
+ String[] lhsColumns,
+ boolean nullable,
+ int currentDepth,
+ CascadeStyle cascadeStyle) throws MappingException {
+ if ( !isJoinedFetchEnabled( associationType, config, cascadeStyle ) ) {
+ return -1;
+ }
+ if ( isTooDeep(currentDepth) || ( associationType.isCollectionType() &&
isTooManyCollections() ) ) {
+ return -1;
+ }
+ if ( isDuplicateAssociation( lhsTable, lhsColumns, associationType ) ) {
+ return -1;
+ }
+ return getJoinType( nullable, currentDepth );
+ }
+ /**
+ * 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)}.
+ *
+ * @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 currentDepth The current join depth
+ * @throws org.hibernate.MappingException ???
+ */
+ private void walkEntityTree(
+ final OuterJoinLoadable persister,
+ final String alias,
+ final String path,
+ final int currentDepth) throws MappingException {
int n = persister.countSubclassProperties();
- for ( int i=0; i<n; i++ ) {
+ for ( int i = 0; i < n; i++ ) {
Type type = persister.getSubclassPropertyType(i);
if ( type.isAssociationType() ) {
walkEntityAssociationTree(
- (AssociationType) type,
+ ( AssociationType ) type,
persister,
i,
alias,
@@ -414,7 +520,7 @@
}
else if ( type.isComponentType() ) {
walkComponentTree(
- (AbstractComponentType) type,
+ ( AbstractComponentType ) type,
i,
0,
persister,
@@ -428,28 +534,34 @@
/**
* For a component, add to a list of associations to be fetched by outerjoin
+ *
+ *
+ * @param componentType The component type to be walked.
+ * @param propertyNumber The property number for the component property (relative to
+ * persister).
+ * @param begin todo unknowm
+ * @param persister The owner of the component property
+ * @param alias The root alias
+ * @param path The property access path
+ * @param currentDepth The current join depth
+ * @throws org.hibernate.MappingException ???
*/
private void walkComponentTree(
- final AbstractComponentType componentType,
- final int propertyNumber,
- int begin,
- final OuterJoinLoadable persister,
- final String alias,
- final String path,
- final int currentDepth
- ) throws MappingException {
-
+ final AbstractComponentType componentType,
+ final int propertyNumber,
+ int begin,
+ final OuterJoinLoadable persister,
+ final String alias,
+ final String path,
+ final int currentDepth) throws MappingException {
Type[] types = componentType.getSubtypes();
String[] propertyNames = componentType.getPropertyNames();
- for ( int i=0; i <types.length; i++ ) {
-
+ for ( int i = 0; i < types.length; i++ ) {
if ( types[i].isAssociationType() ) {
AssociationType associationType = (AssociationType) types[i];
-
String[] aliasedLhsColumns = JoinHelper.getAliasedLHSColumnNames(
associationType, alias, propertyNumber, begin, persister, getFactory()
);
-
String[] lhsColumns = JoinHelper.getLHSColumnNames(
associationType, propertyNumber, begin, persister, getFactory()
);
@@ -458,15 +570,17 @@
String subpath = subPath( path, propertyNames[i] );
final boolean[] propertyNullability = componentType.getPropertyNullability();
final int joinType = getJoinType(
+ persister,
+ subpath,
+ propertyNumber,
associationType,
componentType.getFetchMode(i),
- subpath,
+ componentType.getCascadeStyle(i),
lhsTable,
lhsColumns,
propertyNullability==null || propertyNullability[i],
- currentDepth,
- componentType.getCascadeStyle(i)
- );
+ currentDepth
+ );
addAssociationToJoinTreeIfNecessary(
associationType,
aliasedLhsColumns,
@@ -474,23 +588,22 @@
subpath,
currentDepth,
joinType
- );
+ );
}
else if ( types[i].isComponentType() ) {
String subpath = subPath( path, propertyNames[i] );
walkComponentTree(
- (AbstractComponentType) types[i],
+ ( AbstractComponentType ) types[i],
propertyNumber,
begin,
persister,
alias,
subpath,
currentDepth
- );
+ );
}
-
- begin+=types[i].getColumnSpan( getFactory() );
+ begin += types[i].getColumnSpan( getFactory() );
}
}
@@ -499,13 +612,12 @@
* For a composite element, add to a list of associations to be fetched by outerjoin
*/
private void walkCompositeElementTree(
- final AbstractComponentType compositeType,
- final String[] cols,
- final QueryableCollection persister,
- final String alias,
- final String path,
- final int currentDepth)
- throws MappingException {
+ final AbstractComponentType compositeType,
+ final String[] cols,
+ final QueryableCollection persister,
+ final String alias,
+ final String path,
+ final int currentDepth) throws MappingException {
Type[] types = compositeType.getSubtypes();
String[] propertyNames = compositeType.getPropertyNames();
@@ -571,42 +683,15 @@
}
/**
- * Get the join type (inner, outer, etc) or -1 if the
- * association should not be joined. Override on
- * subclasses.
- */
- protected int getJoinType(
- AssociationType type,
- FetchMode config,
- String path,
- String lhsTable,
- String[] lhsColumns,
- boolean nullable,
- int currentDepth,
- CascadeStyle cascadeStyle)
- throws MappingException {
-
- if ( !isJoinedFetchEnabled(type, config, cascadeStyle) ) return -1;
-
- if ( isTooDeep(currentDepth) || ( type.isCollectionType() &&
isTooManyCollections() ) ) return -1;
-
- final boolean dupe = isDuplicateAssociation(lhsTable, lhsColumns, type);
- if (dupe) return -1;
-
- return getJoinType(nullable, currentDepth);
-
- }
-
- /**
* Use an inner join if it is a non-null association and this
* is the "first" join in a series
*/
protected int getJoinType(boolean nullable, int currentDepth) {
//TODO: this is too conservative; if all preceding joins were
// also inner joins, we could use an inner join here
- return !nullable && currentDepth==0 ?
- JoinFragment.INNER_JOIN :
- JoinFragment.LEFT_OUTER_JOIN;
+ return !nullable && currentDepth == 0
+ ? JoinFragment.INNER_JOIN
+ : JoinFragment.LEFT_OUTER_JOIN;
}
protected boolean isTooDeep(int currentDepth) {
@@ -654,8 +739,7 @@
protected String generateTableAlias(
final int n,
final String path,
- final Joinable joinable
- ) {
+ final Joinable joinable) {
return StringHelper.generateAlias( joinable.getName(), n );
}
Modified: core/trunk/core/src/main/java/org/hibernate/loader/OuterJoinLoader.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/loader/OuterJoinLoader.java 2008-08-15
21:03:38 UTC (rev 15090)
+++ core/trunk/core/src/main/java/org/hibernate/loader/OuterJoinLoader.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -25,10 +25,12 @@
package org.hibernate.loader;
import java.util.Map;
+import java.util.Set;
import org.hibernate.LockMode;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.Loadable;
import org.hibernate.type.EntityType;
@@ -54,15 +56,17 @@
protected String[] suffixes;
protected String[] collectionSuffixes;
- private Map enabledFilters;
-
- protected final Dialect getDialect() {
+ private LoadQueryInfluencers loadQueryInfluencers;
+
+ protected final Dialect getDialect() {
return getFactory().getDialect();
}
- public OuterJoinLoader(SessionFactoryImplementor factory, Map enabledFilters) {
- super(factory);
- this.enabledFilters = enabledFilters;
+ public OuterJoinLoader(
+ SessionFactoryImplementor factory,
+ LoadQueryInfluencers loadQueryInfluencers) {
+ super( factory );
+ this.loadQueryInfluencers = loadQueryInfluencers;
}
protected String[] getSuffixes() {
@@ -92,9 +96,9 @@
protected LockMode[] getLockModes(Map lockModes) {
return lockModeArray;
}
-
- public Map getEnabledFilters() {
- return enabledFilters;
+
+ public LoadQueryInfluencers getLoadQueryInfluencers() {
+ return loadQueryInfluencers;
}
protected final String[] getAliases() {
Modified:
core/trunk/core/src/main/java/org/hibernate/loader/OuterJoinableAssociation.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/loader/OuterJoinableAssociation.java 2008-08-15
21:03:38 UTC (rev 15090)
+++
core/trunk/core/src/main/java/org/hibernate/loader/OuterJoinableAssociation.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -36,6 +36,12 @@
import org.hibernate.type.AssociationType;
import org.hibernate.type.EntityType;
+/**
+ * Part of the Hibernate SQL rendering internals. This class represents
+ * a joinable association.
+ *
+ * @author Gavin King
+ */
public final class OuterJoinableAssociation {
private final AssociationType joinableType;
private final Joinable joinable;
@@ -48,14 +54,13 @@
private final Map enabledFilters;
public OuterJoinableAssociation(
- AssociationType joinableType,
- String lhsAlias,
- String[] lhsColumns,
- String rhsAlias,
- int joinType,
- SessionFactoryImplementor factory,
- Map enabledFilters)
- throws MappingException {
+ AssociationType joinableType,
+ String lhsAlias,
+ String[] lhsColumns,
+ String rhsAlias,
+ int joinType,
+ SessionFactoryImplementor factory,
+ Map enabledFilters) throws MappingException {
this.joinableType = joinableType;
this.lhsAlias = lhsAlias;
this.lhsColumns = lhsColumns;
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 2008-08-15
21:03:38 UTC (rev 15090)
+++
core/trunk/core/src/main/java/org/hibernate/loader/collection/BasicCollectionJoinWalker.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -34,9 +34,12 @@
import org.hibernate.LockMode;
import org.hibernate.MappingException;
import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.engine.LoadQueryInfluencers;
+import org.hibernate.engine.CascadeStyle;
import org.hibernate.loader.BasicLoader;
import org.hibernate.loader.OuterJoinableAssociation;
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;
@@ -58,10 +61,9 @@
int batchSize,
String subquery,
SessionFactoryImplementor factory,
- Map enabledFilters)
- throws MappingException {
+ LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
- super(factory, enabledFilters);
+ super( factory, loadQueryInfluencers );
this.collectionPersister = collectionPersister;
@@ -71,26 +73,25 @@
List allAssociations = new ArrayList();
allAssociations.addAll(associations);
- allAssociations.add( new OuterJoinableAssociation(
- collectionPersister.getCollectionType(),
- null,
- null,
- alias,
- JoinFragment.LEFT_OUTER_JOIN,
- getFactory(),
- CollectionHelper.EMPTY_MAP
- ) );
-
+ allAssociations.add(
+ new OuterJoinableAssociation(
+ collectionPersister.getCollectionType(),
+ null,
+ null,
+ alias,
+ JoinFragment.LEFT_OUTER_JOIN,
+ getFactory(),
+ CollectionHelper.EMPTY_MAP
+ )
+ );
initPersisters(allAssociations, LockMode.NONE);
initStatementString(alias, batchSize, subquery);
-
}
private void initStatementString(
final String alias,
final int batchSize,
- final String subquery)
- throws MappingException {
+ final String subquery) throws MappingException {
final int joins = countEntityPersisters( associations );
final int collectionJoins = countCollectionPersisters( associations ) + 1;
@@ -106,7 +107,7 @@
);
String manyToManyOrderBy = "";
- String filter = collectionPersister.filterFragment( alias, getEnabledFilters() );
+ String filter = collectionPersister.filterFragment( alias,
getLoadQueryInfluencers().getEnabledFilters() );
if ( collectionPersister.isManyToMany() ) {
// from the collection of associations, locate OJA for the
// ManyToOne corresponding to this persister to fully
@@ -121,9 +122,9 @@
// we found it
filter += collectionPersister.getManyToManyFilterFragment(
oja.getRHSAlias(),
- getEnabledFilters()
+ getLoadQueryInfluencers().getEnabledFilters()
);
- manyToManyOrderBy += collectionPersister.getManyToManyOrderByString(
oja.getRHSAlias() );
+ manyToManyOrderBy += collectionPersister.getManyToManyOrderByString(
oja.getRHSAlias() );
}
}
}
@@ -151,37 +152,36 @@
sql = select.toStatementString();
}
- /**
- * We can use an inner join for first many-to-many association
- */
protected int getJoinType(
- AssociationType type,
- FetchMode config,
- String path,
- Set visitedAssociations,
+ OuterJoinLoadable persister,
+ String path,
+ int propertyNumber,
+ AssociationType associationType,
+ FetchMode metadataFetchMode,
+ CascadeStyle metadataCascadeStyle,
String lhsTable,
String[] lhsColumns,
boolean nullable,
- int currentDepth)
- throws MappingException {
-
+ int currentDepth) throws MappingException {
int joinType = super.getJoinType(
- type,
- config,
- path,
- lhsTable,
- lhsColumns,
- nullable,
- currentDepth,
- null
- );
+ persister,
+ path,
+ propertyNumber,
+ associationType,
+ metadataFetchMode,
+ metadataCascadeStyle,
+ lhsTable,
+ lhsColumns,
+ nullable,
+ currentDepth
+ );
//we can use an inner join for the many-to-many
if ( joinType==JoinFragment.LEFT_OUTER_JOIN && "".equals(path) ) {
joinType=JoinFragment.INNER_JOIN;
}
return joinType;
}
-
+
public String toString() {
return getClass().getName() + '(' + collectionPersister.getRole() +
')';
}
Modified:
core/trunk/core/src/main/java/org/hibernate/loader/collection/BasicCollectionLoader.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/loader/collection/BasicCollectionLoader.java 2008-08-15
21:03:38 UTC (rev 15090)
+++
core/trunk/core/src/main/java/org/hibernate/loader/collection/BasicCollectionLoader.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -24,12 +24,11 @@
*/
package org.hibernate.loader.collection;
-import java.util.Map;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.MappingException;
import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.loader.JoinWalker;
import org.hibernate.persister.collection.QueryableCollection;
@@ -49,18 +48,16 @@
public BasicCollectionLoader(
QueryableCollection collectionPersister,
SessionFactoryImplementor session,
- Map enabledFilters)
- throws MappingException {
- this(collectionPersister, 1, session, enabledFilters);
+ LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
+ this( collectionPersister, 1, session, loadQueryInfluencers );
}
public BasicCollectionLoader(
QueryableCollection collectionPersister,
int batchSize,
SessionFactoryImplementor factory,
- Map enabledFilters)
- throws MappingException {
- this(collectionPersister, batchSize, null, factory, enabledFilters);
+ LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
+ this( collectionPersister, batchSize, null, factory, loadQueryInfluencers );
}
protected BasicCollectionLoader(
@@ -68,18 +65,16 @@
int batchSize,
String subquery,
SessionFactoryImplementor factory,
- Map enabledFilters)
- throws MappingException {
+ LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
+ super( collectionPersister, factory, loadQueryInfluencers );
- super(collectionPersister, factory, enabledFilters);
-
JoinWalker walker = new BasicCollectionJoinWalker(
collectionPersister,
batchSize,
subquery,
factory,
- enabledFilters
- );
+ loadQueryInfluencers
+ );
initFromWalker( walker );
postInstantiate();
Modified:
core/trunk/core/src/main/java/org/hibernate/loader/collection/BatchingCollectionInitializer.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/loader/collection/BatchingCollectionInitializer.java 2008-08-15
21:03:38 UTC (rev 15090)
+++
core/trunk/core/src/main/java/org/hibernate/loader/collection/BatchingCollectionInitializer.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -31,6 +31,7 @@
import org.hibernate.MappingException;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
+import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.loader.Loader;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.collection.QueryableCollection;
@@ -77,42 +78,38 @@
}
public static CollectionInitializer createBatchingOneToManyInitializer(
- final QueryableCollection persister,
- final int maxBatchSize,
- final SessionFactoryImplementor factory,
- final Map enabledFilters)
- throws MappingException {
-
- if ( maxBatchSize>1 ) {
+ final QueryableCollection persister,
+ final int maxBatchSize,
+ final SessionFactoryImplementor factory,
+ final LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
+ if ( maxBatchSize > 1 ) {
int[] batchSizesToCreate = ArrayHelper.getBatchSizes(maxBatchSize);
Loader[] loadersToCreate = new Loader[ batchSizesToCreate.length ];
for ( int i=0; i<batchSizesToCreate.length; i++ ) {
- loadersToCreate[i] = new OneToManyLoader(persister, batchSizesToCreate[i], factory,
enabledFilters);
+ loadersToCreate[i] = new OneToManyLoader( persister, batchSizesToCreate[i], factory,
loadQueryInfluencers );
}
- return new BatchingCollectionInitializer(persister, batchSizesToCreate,
loadersToCreate);
+ return new BatchingCollectionInitializer( persister, batchSizesToCreate,
loadersToCreate );
}
else {
- return new OneToManyLoader(persister, factory, enabledFilters);
+ return new OneToManyLoader( persister, factory, loadQueryInfluencers );
}
}
public static CollectionInitializer createBatchingCollectionInitializer(
- final QueryableCollection persister,
- final int maxBatchSize,
- final SessionFactoryImplementor factory,
- final Map enabledFilters)
- throws MappingException {
-
- if ( maxBatchSize>1 ) {
+ final QueryableCollection persister,
+ final int maxBatchSize,
+ final SessionFactoryImplementor factory,
+ final LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
+ if ( maxBatchSize > 1 ) {
int[] batchSizesToCreate = ArrayHelper.getBatchSizes(maxBatchSize);
Loader[] loadersToCreate = new Loader[ batchSizesToCreate.length ];
for ( int i=0; i<batchSizesToCreate.length; i++ ) {
- loadersToCreate[i] = new BasicCollectionLoader(persister, batchSizesToCreate[i],
factory, enabledFilters);
+ loadersToCreate[i] = new BasicCollectionLoader( persister, batchSizesToCreate[i],
factory, loadQueryInfluencers );
}
return new BatchingCollectionInitializer(persister, batchSizesToCreate,
loadersToCreate);
}
else {
- return new BasicCollectionLoader(persister, factory, enabledFilters);
+ return new BasicCollectionLoader( persister, factory, loadQueryInfluencers );
}
}
Modified:
core/trunk/core/src/main/java/org/hibernate/loader/collection/CollectionJoinWalker.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/loader/collection/CollectionJoinWalker.java 2008-08-15
21:03:38 UTC (rev 15090)
+++
core/trunk/core/src/main/java/org/hibernate/loader/collection/CollectionJoinWalker.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -24,9 +24,8 @@
*/
package org.hibernate.loader.collection;
-import java.util.Map;
-
import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.loader.JoinWalker;
import org.hibernate.util.StringHelper;
@@ -40,8 +39,8 @@
*/
public abstract class CollectionJoinWalker extends JoinWalker {
- public CollectionJoinWalker(SessionFactoryImplementor factory, Map enabledFilters) {
- super( factory, enabledFilters );
+ public CollectionJoinWalker(SessionFactoryImplementor factory, LoadQueryInfluencers
loadQueryInfluencers) {
+ super( factory, loadQueryInfluencers );
}
protected StringBuffer whereString(String alias, String[] columnNames, String subselect,
int batchSize) {
Modified:
core/trunk/core/src/main/java/org/hibernate/loader/collection/CollectionLoader.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/loader/collection/CollectionLoader.java 2008-08-15
21:03:38 UTC (rev 15090)
+++
core/trunk/core/src/main/java/org/hibernate/loader/collection/CollectionLoader.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -25,11 +25,11 @@
package org.hibernate.loader.collection;
import java.io.Serializable;
-import java.util.Map;
import org.hibernate.HibernateException;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
+import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.loader.OuterJoinLoader;
import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.type.Type;
@@ -45,8 +45,11 @@
private final QueryableCollection collectionPersister;
- public CollectionLoader(QueryableCollection collectionPersister,
SessionFactoryImplementor factory, Map enabledFilters) {
- super( factory, enabledFilters );
+ public CollectionLoader(
+ QueryableCollection collectionPersister,
+ SessionFactoryImplementor factory,
+ LoadQueryInfluencers loadQueryInfluencers) {
+ super( factory, loadQueryInfluencers );
this.collectionPersister = collectionPersister;
}
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 2008-08-15
21:03:38 UTC (rev 15090)
+++
core/trunk/core/src/main/java/org/hibernate/loader/collection/OneToManyJoinWalker.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -27,11 +27,11 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import java.util.Map;
import org.hibernate.LockMode;
import org.hibernate.MappingException;
import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.loader.BasicLoader;
import org.hibernate.loader.OuterJoinableAssociation;
import org.hibernate.persister.collection.QueryableCollection;
@@ -67,11 +67,9 @@
int batchSize,
String subquery,
SessionFactoryImplementor factory,
- Map enabledFilters)
- throws MappingException {
+ LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
+ super( factory, loadQueryInfluencers );
- super(factory, enabledFilters);
-
this.oneToManyPersister = oneToManyPersister;
final OuterJoinLoadable elementPersister = (OuterJoinLoadable)
oneToManyPersister.getElementPersister();
@@ -93,7 +91,6 @@
initPersisters(allAssociations, LockMode.NONE);
initStatementString(elementPersister, alias, batchSize, subquery);
-
}
private void initStatementString(
@@ -115,7 +112,7 @@
subquery,
batchSize
);
- String filter = oneToManyPersister.filterFragment( alias, getEnabledFilters() );
+ String filter = oneToManyPersister.filterFragment( alias,
getLoadQueryInfluencers().getEnabledFilters() );
whereString.insert( 0, StringHelper.moveAndToBeginning(filter) );
JoinFragment ojf = mergeOuterJoins(associations);
Modified:
core/trunk/core/src/main/java/org/hibernate/loader/collection/OneToManyLoader.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/loader/collection/OneToManyLoader.java 2008-08-15
21:03:38 UTC (rev 15090)
+++
core/trunk/core/src/main/java/org/hibernate/loader/collection/OneToManyLoader.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -24,12 +24,11 @@
*/
package org.hibernate.loader.collection;
-import java.util.Map;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.MappingException;
import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.loader.JoinWalker;
import org.hibernate.persister.collection.QueryableCollection;
@@ -49,18 +48,16 @@
public OneToManyLoader(
QueryableCollection oneToManyPersister,
SessionFactoryImplementor session,
- Map enabledFilters)
- throws MappingException {
- this(oneToManyPersister, 1, session, enabledFilters);
+ LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
+ this( oneToManyPersister, 1, session, loadQueryInfluencers );
}
public OneToManyLoader(
QueryableCollection oneToManyPersister,
int batchSize,
SessionFactoryImplementor factory,
- Map enabledFilters)
- throws MappingException {
- this(oneToManyPersister, batchSize, null, factory, enabledFilters);
+ LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
+ this( oneToManyPersister, batchSize, null, factory, loadQueryInfluencers );
}
public OneToManyLoader(
@@ -68,22 +65,19 @@
int batchSize,
String subquery,
SessionFactoryImplementor factory,
- Map enabledFilters)
- throws MappingException {
-
- super(oneToManyPersister, factory, enabledFilters);
+ LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
+ super( oneToManyPersister, factory, loadQueryInfluencers );
JoinWalker walker = new OneToManyJoinWalker(
oneToManyPersister,
batchSize,
subquery,
factory,
- enabledFilters
- );
+ loadQueryInfluencers
+ );
initFromWalker( walker );
postInstantiate();
-
log.debug( "Static select for one-to-many " + oneToManyPersister.getRole() +
": " + getSQLString() );
}
Modified:
core/trunk/core/src/main/java/org/hibernate/loader/collection/SubselectCollectionLoader.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/loader/collection/SubselectCollectionLoader.java 2008-08-15
21:03:38 UTC (rev 15090)
+++
core/trunk/core/src/main/java/org/hibernate/loader/collection/SubselectCollectionLoader.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -35,6 +35,7 @@
import org.hibernate.engine.QueryParameters;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
+import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.type.Type;
@@ -57,10 +58,8 @@
QueryParameters queryParameters,
Map namedParameterLocMap,
SessionFactoryImplementor factory,
- Map enabledFilters)
- throws MappingException {
-
- super(persister, 1, subquery, factory, enabledFilters);
+ LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
+ super( persister, 1, subquery, factory, loadQueryInfluencers );
keys = new Serializable[ entityKeys.size() ];
Iterator iter = entityKeys.iterator();
@@ -77,7 +76,7 @@
}
public void initialize(Serializable id, SessionImplementor session)
- throws HibernateException {
+ throws HibernateException {
loadCollectionSubselect(
session,
keys,
@@ -85,7 +84,7 @@
types,
namedParameters,
getKeyType()
- );
+ );
}
public int[] getNamedParameterLocs(String name) {
Modified:
core/trunk/core/src/main/java/org/hibernate/loader/collection/SubselectOneToManyLoader.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/loader/collection/SubselectOneToManyLoader.java 2008-08-15
21:03:38 UTC (rev 15090)
+++
core/trunk/core/src/main/java/org/hibernate/loader/collection/SubselectOneToManyLoader.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -35,6 +35,7 @@
import org.hibernate.engine.QueryParameters;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
+import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.type.Type;
@@ -57,10 +58,8 @@
QueryParameters queryParameters,
Map namedParameterLocMap,
SessionFactoryImplementor factory,
- Map enabledFilters)
- throws MappingException {
-
- super(persister, 1, subquery, factory, enabledFilters);
+ LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
+ super( persister, 1, subquery, factory, loadQueryInfluencers );
keys = new Serializable[ entityKeys.size() ];
Iterator iter = entityKeys.iterator();
@@ -73,11 +72,9 @@
this.types = queryParameters.getFilteredPositionalParameterTypes();
this.values = queryParameters.getFilteredPositionalParameterValues();
this.namedParameterLocMap = namedParameterLocMap;
-
}
- public void initialize(Serializable id, SessionImplementor session)
- throws HibernateException {
+ public void initialize(Serializable id, SessionImplementor session) throws
HibernateException {
loadCollectionSubselect(
session,
keys,
@@ -85,7 +82,7 @@
types,
namedParameters,
getKeyType()
- );
+ );
}
public int[] getNamedParameterLocs(String name) {
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 2008-08-15
21:03:38 UTC (rev 15090)
+++
core/trunk/core/src/main/java/org/hibernate/loader/criteria/CriteriaJoinWalker.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -26,7 +26,6 @@
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
import java.util.Set;
import org.hibernate.Criteria;
@@ -35,6 +34,7 @@
import org.hibernate.MappingException;
import org.hibernate.engine.CascadeStyle;
import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.impl.CriteriaImpl;
import org.hibernate.loader.AbstractEntityJoinWalker;
import org.hibernate.persister.entity.Joinable;
@@ -78,8 +78,8 @@
final SessionFactoryImplementor factory,
final CriteriaImpl criteria,
final String rootEntityName,
- final Map enabledFilters) {
- this(persister, translator, factory, criteria, rootEntityName, enabledFilters, null);
+ final LoadQueryInfluencers loadQueryInfluencers) {
+ this( persister, translator, factory, criteria, rootEntityName, loadQueryInfluencers,
null );
}
public CriteriaJoinWalker(
@@ -88,9 +88,9 @@
final SessionFactoryImplementor factory,
final CriteriaImpl criteria,
final String rootEntityName,
- final Map enabledFilters,
+ final LoadQueryInfluencers loadQueryInfluencers,
final String alias) {
- super(persister, factory, enabledFilters, alias);
+ super( persister, factory, loadQueryInfluencers, alias );
this.translator = translator;
@@ -119,16 +119,17 @@
}
protected int getJoinType(
- AssociationType type,
- FetchMode config,
- String path,
+ OuterJoinLoadable persister,
+ final String path,
+ int propertyNumber,
+ AssociationType associationType,
+ FetchMode metadataFetchMode,
+ CascadeStyle metadataCascadeStyle,
String lhsTable,
String[] lhsColumns,
- boolean nullable,
- int currentDepth, CascadeStyle cascadeStyle)
- throws MappingException {
-
- if ( translator.isJoin(path) ) {
+ final boolean nullable,
+ final int currentDepth) throws MappingException {
+ if ( translator.isJoin( path ) ) {
return translator.getJoinType( path );
}
else {
@@ -136,23 +137,30 @@
return -1;
}
else {
- FetchMode fetchMode = translator.getRootCriteria()
- .getFetchMode(path);
- if ( isDefaultFetchMode(fetchMode) ) {
- return super.getJoinType(
- type,
- config,
- path,
- lhsTable,
- lhsColumns,
- nullable,
- currentDepth, cascadeStyle
+ FetchMode fetchMode = translator.getRootCriteria().getFetchMode( path );
+ if ( isDefaultFetchMode( fetchMode ) ) {
+ if ( isJoinFetchEnabledByProfile( persister, path, propertyNumber ) ) {
+ return getJoinType( nullable, currentDepth );
+ }
+ else {
+ return super.getJoinType(
+ persister,
+ path,
+ propertyNumber,
+ associationType,
+ metadataFetchMode,
+ metadataCascadeStyle,
+ lhsTable,
+ lhsColumns,
+ nullable,
+ currentDepth
);
+ }
}
else {
- if ( fetchMode==FetchMode.JOIN ) {
- isDuplicateAssociation(lhsTable, lhsColumns, type); //deliberately ignore return
value!
- return getJoinType(nullable, currentDepth);
+ if ( fetchMode == FetchMode.JOIN ) {
+ isDuplicateAssociation( lhsTable, lhsColumns, associationType ); //deliberately
ignore return value!
+ return getJoinType( nullable, currentDepth );
}
else {
return -1;
@@ -172,7 +180,7 @@
*/
protected String getWhereFragment() throws MappingException {
return super.getWhereFragment() +
- ( (Queryable) getPersister() ).filterFragment( getAlias(), getEnabledFilters() );
+ ( (Queryable) getPersister() ).filterFragment( getAlias(),
getLoadQueryInfluencers().getEnabledFilters() );
}
protected String generateTableAlias(int n, String path, Joinable joinable) {
Modified: core/trunk/core/src/main/java/org/hibernate/loader/criteria/CriteriaLoader.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/loader/criteria/CriteriaLoader.java 2008-08-15
21:03:38 UTC (rev 15090)
+++
core/trunk/core/src/main/java/org/hibernate/loader/criteria/CriteriaLoader.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -30,7 +30,6 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.Iterator;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
@@ -41,6 +40,7 @@
import org.hibernate.engine.QueryParameters;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
+import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.impl.CriteriaImpl;
import org.hibernate.loader.OuterJoinLoader;
import org.hibernate.persister.entity.OuterJoinLoadable;
@@ -75,9 +75,8 @@
final SessionFactoryImplementor factory,
final CriteriaImpl criteria,
final String rootEntityName,
- final Map enabledFilters)
- throws HibernateException {
- super(factory, enabledFilters);
+ final LoadQueryInfluencers loadQueryInfluencers) throws HibernateException {
+ super( factory, loadQueryInfluencers );
translator = new CriteriaQueryTranslator(
factory,
@@ -94,7 +93,7 @@
factory,
criteria,
rootEntityName,
- enabledFilters
+ loadQueryInfluencers
);
initFromWalker(walker);
Modified:
core/trunk/core/src/main/java/org/hibernate/loader/entity/AbstractEntityLoader.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/loader/entity/AbstractEntityLoader.java 2008-08-15
21:03:38 UTC (rev 15090)
+++
core/trunk/core/src/main/java/org/hibernate/loader/entity/AbstractEntityLoader.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -29,12 +29,14 @@
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.HibernateException;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
+import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.loader.OuterJoinLoader;
import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.transform.ResultTransformer;
@@ -52,8 +54,8 @@
OuterJoinLoadable persister,
Type uniqueKeyType,
SessionFactoryImplementor factory,
- Map enabledFilters) {
- super( factory, enabledFilters );
+ LoadQueryInfluencers loadQueryInfluencers) {
+ super( factory, loadQueryInfluencers );
this.uniqueKeyType = uniqueKeyType;
this.entityName = persister.getEntityName();
this.persister = persister;
Modified:
core/trunk/core/src/main/java/org/hibernate/loader/entity/BatchingEntityLoader.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/loader/entity/BatchingEntityLoader.java 2008-08-15
21:03:38 UTC (rev 15090)
+++
core/trunk/core/src/main/java/org/hibernate/loader/entity/BatchingEntityLoader.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -28,12 +28,14 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.MappingException;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
+import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.loader.Loader;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.OuterJoinLoadable;
@@ -111,19 +113,18 @@
final int maxBatchSize,
final LockMode lockMode,
final SessionFactoryImplementor factory,
- final Map enabledFilters)
- throws MappingException {
+ final LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
if ( maxBatchSize>1 ) {
int[] batchSizesToCreate = ArrayHelper.getBatchSizes(maxBatchSize);
Loader[] loadersToCreate = new Loader[ batchSizesToCreate.length ];
for ( int i=0; i<batchSizesToCreate.length; i++ ) {
- loadersToCreate[i] = new EntityLoader(persister, batchSizesToCreate[i], lockMode,
factory, enabledFilters);
+ loadersToCreate[i] = new EntityLoader(persister, batchSizesToCreate[i], lockMode,
factory, loadQueryInfluencers);
}
return new BatchingEntityLoader(persister, batchSizesToCreate, loadersToCreate);
}
else {
- return new EntityLoader(persister, lockMode, factory, enabledFilters);
+ return new EntityLoader(persister, lockMode, factory, loadQueryInfluencers);
}
}
Modified:
core/trunk/core/src/main/java/org/hibernate/loader/entity/CascadeEntityJoinWalker.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/loader/entity/CascadeEntityJoinWalker.java 2008-08-15
21:03:38 UTC (rev 15090)
+++
core/trunk/core/src/main/java/org/hibernate/loader/entity/CascadeEntityJoinWalker.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -30,6 +30,7 @@
import org.hibernate.engine.CascadeStyle;
import org.hibernate.engine.CascadingAction;
import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.loader.AbstractEntityJoinWalker;
import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.type.AssociationType;
@@ -41,7 +42,7 @@
public CascadeEntityJoinWalker(OuterJoinLoadable persister, CascadingAction action,
SessionFactoryImplementor factory)
throws MappingException {
- super( persister, factory, CollectionHelper.EMPTY_MAP );
+ super( persister, factory, LoadQueryInfluencers.NONE );
this.cascadeAction = action;
StringBuffer whereCondition = whereString( getAlias(),
persister.getIdentifierColumnNames(), 1 )
//include the discriminator and class-level where, but not filters
Modified:
core/trunk/core/src/main/java/org/hibernate/loader/entity/CascadeEntityLoader.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/loader/entity/CascadeEntityLoader.java 2008-08-15
21:03:38 UTC (rev 15090)
+++
core/trunk/core/src/main/java/org/hibernate/loader/entity/CascadeEntityLoader.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -27,29 +27,28 @@
import org.hibernate.MappingException;
import org.hibernate.engine.CascadingAction;
import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.loader.JoinWalker;
import org.hibernate.persister.entity.OuterJoinLoadable;
-import org.hibernate.util.CollectionHelper;
public class CascadeEntityLoader extends AbstractEntityLoader {
public CascadeEntityLoader(
OuterJoinLoadable persister,
CascadingAction action,
- SessionFactoryImplementor factory)
- throws MappingException {
+ SessionFactoryImplementor factory) throws MappingException {
super(
persister,
persister.getIdentifierType(),
- factory,
- CollectionHelper.EMPTY_MAP
- );
+ factory,
+ LoadQueryInfluencers.NONE
+ );
JoinWalker walker = new CascadeEntityJoinWalker(
persister,
action,
factory
- );
+ );
initFromWalker( walker );
postInstantiate();
Modified:
core/trunk/core/src/main/java/org/hibernate/loader/entity/CollectionElementLoader.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/loader/entity/CollectionElementLoader.java 2008-08-15
21:03:38 UTC (rev 15090)
+++
core/trunk/core/src/main/java/org/hibernate/loader/entity/CollectionElementLoader.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -27,7 +27,6 @@
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
-import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -36,6 +35,7 @@
import org.hibernate.MappingException;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
+import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.loader.JoinWalker;
import org.hibernate.loader.OuterJoinLoader;
import org.hibernate.persister.collection.QueryableCollection;
@@ -61,9 +61,8 @@
public CollectionElementLoader(
QueryableCollection collectionPersister,
SessionFactoryImplementor factory,
- Map enabledFilters)
- throws MappingException {
- super(factory, enabledFilters);
+ LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
+ super( factory, loadQueryInfluencers );
this.keyType = collectionPersister.getKeyType();
this.indexType = collectionPersister.getIndexType();
@@ -79,7 +78,7 @@
1,
LockMode.NONE,
factory,
- enabledFilters
+ loadQueryInfluencers
);
initFromWalker( walker );
@@ -130,5 +129,4 @@
return true;
}
-
}
\ No newline at end of file
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 2008-08-15
21:03:38 UTC (rev 15090)
+++
core/trunk/core/src/main/java/org/hibernate/loader/entity/EntityJoinWalker.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -25,13 +25,16 @@
package org.hibernate.loader.entity;
import java.util.Collections;
-import java.util.Map;
+import java.util.Iterator;
import org.hibernate.FetchMode;
import org.hibernate.LockMode;
import org.hibernate.MappingException;
import org.hibernate.engine.CascadeStyle;
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.loader.AbstractEntityJoinWalker;
import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.type.AssociationType;
@@ -52,28 +55,47 @@
int batchSize,
LockMode lockMode,
SessionFactoryImplementor factory,
- Map enabledFilters)
- throws MappingException {
- super(persister, factory, enabledFilters);
+ LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
+ super( persister, factory, loadQueryInfluencers );
this.lockMode = lockMode;
StringBuffer whereCondition = whereString( getAlias(), uniqueKey, batchSize )
- //include the discriminator and class-level where, but not filters
- .append( persister.filterFragment( getAlias(), Collections.EMPTY_MAP ) );
+ //include the discriminator and class-level where, but not filters
+ .append( persister.filterFragment( getAlias(), Collections.EMPTY_MAP ) );
initAll( whereCondition.toString(), "", lockMode );
-
}
- /**
- * Disable outer join fetching if this loader obtains an
- * upgrade lock mode
- */
- protected boolean isJoinedFetchEnabled(AssociationType type, FetchMode config,
CascadeStyle cascadeStyle) {
- return lockMode.greaterThan(LockMode.READ) ?
- false :
- super.isJoinedFetchEnabled(type, config, cascadeStyle);
+ protected int getJoinType(
+ OuterJoinLoadable persister,
+ String path,
+ int propertyNumber,
+ AssociationType associationType,
+ FetchMode metadataFetchMode,
+ CascadeStyle metadataCascadeStyle,
+ String lhsTable,
+ String[] lhsColumns,
+ boolean nullable,
+ int currentDepth) throws MappingException {
+ // NOTE : we override this form here specifically to account for
+ // fetch profiles.
+ // TODO : how to best handle criteria queries?
+ if ( lockMode.greaterThan( LockMode.READ ) ) {
+ return -1;
+ }
+ if ( isTooDeep( currentDepth )
+ || ( associationType.isCollectionType() && isTooManyCollections() ) ) {
+ return -1;
+ }
+ if ( !isJoinedFetchEnabledInMapping( metadataFetchMode, associationType )
+ && !isJoinFetchEnabledByProfile( persister, path, propertyNumber ) ) {
+ return -1;
+ }
+ if ( isDuplicateAssociation( lhsTable, lhsColumns, associationType ) ) {
+ return -1;
+ }
+ return getJoinType( nullable, currentDepth );
}
public String getComment() {
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 2008-08-15
21:03:38 UTC (rev 15090)
+++ core/trunk/core/src/main/java/org/hibernate/loader/entity/EntityLoader.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -25,12 +25,14 @@
package org.hibernate.loader.entity;
import java.util.Map;
+import java.util.Set;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.MappingException;
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;
@@ -51,9 +53,8 @@
OuterJoinLoadable persister,
LockMode lockMode,
SessionFactoryImplementor factory,
- Map enabledFilters)
- throws MappingException {
- this(persister, 1, lockMode, factory, enabledFilters);
+ LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
+ this( persister, 1, lockMode, factory, loadQueryInfluencers );
}
public EntityLoader(
@@ -61,16 +62,15 @@
int batchSize,
LockMode lockMode,
SessionFactoryImplementor factory,
- Map enabledFilters)
- throws MappingException {
- this(
- persister,
+ LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
+ this(
+ persister,
persister.getIdentifierColumnNames(),
persister.getIdentifierType(),
batchSize,
lockMode,
factory,
- enabledFilters
+ loadQueryInfluencers
);
}
@@ -81,9 +81,8 @@
int batchSize,
LockMode lockMode,
SessionFactoryImplementor factory,
- Map enabledFilters)
- throws MappingException {
- super(persister, uniqueKeyType, factory, enabledFilters);
+ LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
+ super( persister, uniqueKeyType, factory, loadQueryInfluencers );
JoinWalker walker = new EntityJoinWalker(
persister,
@@ -91,8 +90,8 @@
batchSize,
lockMode,
factory,
- enabledFilters
- );
+ loadQueryInfluencers
+ );
initFromWalker( walker );
postInstantiate();
@@ -103,9 +102,10 @@
}
- public Object loadByUniqueKey(SessionImplementor session, Object key)
- throws HibernateException {
- return load(session, key, null, null);
+ public Object loadByUniqueKey(
+ SessionImplementor session,
+ Object key) throws HibernateException {
+ return load( session, key, null, null );
}
protected boolean isSingleRowLoader() {
Added: core/trunk/core/src/main/java/org/hibernate/mapping/FetchProfile.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/mapping/FetchProfile.java
(rev 0)
+++ core/trunk/core/src/main/java/org/hibernate/mapping/FetchProfile.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -0,0 +1,101 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC 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.
+ *
+ * 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.mapping;
+
+import java.util.LinkedHashSet;
+
+/**
+ * A fetch profile allows a user to dynamically modify the fetching
+ * strategy used for particular associations at runtime, whereas that
+ * information was historically only statically defined in the metadata.
+ *
+ * @author Steve Ebersole
+ */
+public class FetchProfile {
+ private final String name;
+ private LinkedHashSet fetches = new LinkedHashSet();
+
+ public FetchProfile(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public LinkedHashSet getFetches() {
+ return fetches;
+ }
+
+ public void addFetch(String entity, String association, String style) {
+ fetches.add( new Fetch( entity, association, style ) );
+ }
+
+ public boolean equals(Object o) {
+ if ( this == o ) {
+ return true;
+ }
+ if ( o == null || getClass() != o.getClass() ) {
+ return false;
+ }
+
+ FetchProfile that = ( FetchProfile ) o;
+
+ return name.equals( that.name );
+
+ }
+
+ public int hashCode() {
+ return name.hashCode();
+ }
+
+
+ /**
+ * Defines an individual association fetch within the given profile.
+ */
+ public static class Fetch {
+ private final String entity;
+ private final String association;
+ private final String style;
+
+ public Fetch(String entity, String association, String style) {
+ this.entity = entity;
+ this.association = association;
+ this.style = style;
+ }
+
+ public String getEntity() {
+ return entity;
+ }
+
+ public String getAssociation() {
+ return association;
+ }
+
+ public String getStyle() {
+ return style;
+ }
+ }
+}
Modified:
core/trunk/core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java 2008-08-15
21:03:38 UTC (rev 15090)
+++
core/trunk/core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -58,6 +58,7 @@
import org.hibernate.engine.SessionImplementor;
import org.hibernate.engine.SubselectFetch;
import org.hibernate.engine.ExecuteUpdateResultCheckStyle;
+import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.exception.SQLExceptionConverter;
import org.hibernate.id.IdentifierGenerator;
@@ -561,7 +562,7 @@
public void postInstantiate() throws MappingException {
initializer = queryLoaderName == null ?
- createCollectionInitializer( CollectionHelper.EMPTY_MAP ) :
+ createCollectionInitializer( LoadQueryInfluencers.NONE ) :
new NamedQueryCollectionInitializer( queryLoaderName, this );
}
@@ -601,7 +602,7 @@
return initializer;
}
else {
- return createCollectionInitializer( session.getEnabledFilters() );
+ return createCollectionInitializer( session.getLoadQueryInfluencers() );
}
}
@@ -637,7 +638,7 @@
protected abstract CollectionInitializer createSubselectInitializer(SubselectFetch
subselect, SessionImplementor session);
- protected abstract CollectionInitializer createCollectionInitializer(Map
enabledFilters)
+ protected abstract CollectionInitializer
createCollectionInitializer(LoadQueryInfluencers loadQueryInfluencers)
throws MappingException;
public CollectionRegionAccessStrategy getCacheAccessStrategy() {
Modified:
core/trunk/core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java 2008-08-15
21:03:38 UTC (rev 15090)
+++
core/trunk/core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -42,6 +42,7 @@
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.engine.SubselectFetch;
+import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.loader.collection.BatchingCollectionInitializer;
import org.hibernate.loader.collection.CollectionInitializer;
@@ -315,9 +316,9 @@
*
* @see org.hibernate.loader.collection.BasicCollectionLoader
*/
- protected CollectionInitializer createCollectionInitializer(java.util.Map
enabledFilters)
+ protected CollectionInitializer createCollectionInitializer(LoadQueryInfluencers
loadQueryInfluencers)
throws MappingException {
- return BatchingCollectionInitializer.createBatchingCollectionInitializer( this,
batchSize, getFactory(), enabledFilters );
+ return BatchingCollectionInitializer.createBatchingCollectionInitializer( this,
batchSize, getFactory(), loadQueryInfluencers );
}
public String fromJoinFragment(String alias, boolean innerJoin, boolean
includeSubclasses) {
@@ -336,8 +337,8 @@
subselect.getQueryParameters(),
subselect.getNamedParameterLocMap(),
session.getFactory(),
- session.getEnabledFilters()
- );
+ session.getLoadQueryInfluencers()
+ );
}
}
Modified:
core/trunk/core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java 2008-08-15
21:03:38 UTC (rev 15090)
+++
core/trunk/core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -40,6 +40,7 @@
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.engine.SubselectFetch;
+import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.loader.collection.BatchingCollectionInitializer;
import org.hibernate.loader.collection.CollectionInitializer;
@@ -338,8 +339,9 @@
*
* @see org.hibernate.loader.collection.OneToManyLoader
*/
- protected CollectionInitializer createCollectionInitializer(java.util.Map
enabledFilters) throws MappingException {
- return BatchingCollectionInitializer.createBatchingOneToManyInitializer( this,
batchSize, getFactory(), enabledFilters );
+ protected CollectionInitializer createCollectionInitializer(LoadQueryInfluencers
loadQueryInfluencers)
+ throws MappingException {
+ return BatchingCollectionInitializer.createBatchingOneToManyInitializer( this,
batchSize, getFactory(), loadQueryInfluencers );
}
public String fromJoinFragment(String alias,
@@ -375,12 +377,12 @@
subselect.getQueryParameters(),
subselect.getNamedParameterLocMap(),
session.getFactory(),
- session.getEnabledFilters()
+ session.getLoadQueryInfluencers()
);
}
public Object getElementByIndex(Serializable key, Object index, SessionImplementor
session, Object owner) {
- return new CollectionElementLoader( this, getFactory(), session.getEnabledFilters() )
+ return new CollectionElementLoader( this, getFactory(),
session.getLoadQueryInfluencers() )
.loadElement( session, key, incrementIndexByBase(index) );
}
Modified:
core/trunk/core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java 2008-08-15
21:03:38 UTC (rev 15090)
+++
core/trunk/core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -52,7 +52,6 @@
import org.hibernate.jdbc.Expectations;
import org.hibernate.jdbc.TooManyRowsAffectedException;
import org.hibernate.dialect.lock.LockingStrategy;
-import org.hibernate.cache.CacheConcurrencyStrategy;
import org.hibernate.cache.CacheKey;
import org.hibernate.cache.access.EntityRegionAccessStrategy;
import org.hibernate.cache.entry.CacheEntry;
@@ -69,6 +68,7 @@
import org.hibernate.engine.ExecuteUpdateResultCheckStyle;
import org.hibernate.engine.EntityKey;
import org.hibernate.engine.ValueInclusion;
+import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.PostInsertIdentifierGenerator;
@@ -109,7 +109,6 @@
import org.hibernate.type.TypeFactory;
import org.hibernate.type.VersionType;
import org.hibernate.util.ArrayHelper;
-import org.hibernate.util.CollectionHelper;
import org.hibernate.util.FilterHelper;
import org.hibernate.util.StringHelper;
@@ -196,6 +195,8 @@
// dynamic filters attached to the class-level
private final FilterHelper filterHelper;
+ private final Set affectingFetchProfileNames = new HashSet();
+
private final Map uniqueKeyLoaders = new HashMap();
private final Map lockers = new HashMap();
private final Map loaders = new HashMap();
@@ -1667,26 +1668,27 @@
}
- public Object loadByUniqueKey(String propertyName, Object uniqueKey, SessionImplementor
session)
- throws HibernateException {
- return getAppropriateUniqueKeyLoader( propertyName, session.getEnabledFilters() )
- .loadByUniqueKey( session, uniqueKey );
+ public Object loadByUniqueKey(
+ String propertyName,
+ Object uniqueKey,
+ SessionImplementor session) throws HibernateException {
+ return getAppropriateUniqueKeyLoader( propertyName, session ).loadByUniqueKey( session,
uniqueKey );
}
- private EntityLoader getAppropriateUniqueKeyLoader(String propertyName, Map
enabledFilters) {
-
- final boolean useStaticLoader = ( enabledFilters == null || enabledFilters.isEmpty() )
+ private EntityLoader getAppropriateUniqueKeyLoader(String propertyName,
SessionImplementor session) {
+ final boolean useStaticLoader = !session.getLoadQueryInfluencers().hasEnabledFilters()
+ && !session.getLoadQueryInfluencers().hasEnabledFetchProfiles()
&& propertyName.indexOf('.')<0; //ugly little workaround for fact
that createUniqueKeyLoaders() does not handle component properties
if ( useStaticLoader ) {
- return (EntityLoader) uniqueKeyLoaders.get( propertyName );
+ return ( EntityLoader ) uniqueKeyLoaders.get( propertyName );
}
else {
return createUniqueKeyLoader(
- propertyMapping.toType(propertyName),
- propertyMapping.toColumns(propertyName),
- enabledFilters
- );
+ propertyMapping.toType( propertyName ),
+ propertyMapping.toColumns( propertyName ),
+ session.getLoadQueryInfluencers()
+ );
}
}
@@ -1705,21 +1707,31 @@
createUniqueKeyLoader(
propertyTypes[i],
getPropertyColumnNames( i ),
- CollectionHelper.EMPTY_MAP
- )
- );
+ LoadQueryInfluencers.NONE
+ )
+ );
//TODO: create uk loaders for component properties
}
}
}
- private EntityLoader createUniqueKeyLoader(Type uniqueKeyType, String[] columns, Map
enabledFilters) {
+ private EntityLoader createUniqueKeyLoader(
+ Type uniqueKeyType,
+ String[] columns,
+ LoadQueryInfluencers loadQueryInfluencers) {
if ( uniqueKeyType.isEntityType() ) {
String className = ( ( EntityType ) uniqueKeyType ).getAssociatedEntityName();
uniqueKeyType = getFactory().getEntityPersister( className ).getIdentifierType();
}
-
- return new EntityLoader( this, columns, uniqueKeyType, 1, LockMode.NONE, getFactory(),
enabledFilters );
+ return new EntityLoader(
+ this,
+ columns,
+ uniqueKeyType,
+ 1,
+ LockMode.NONE,
+ getFactory(),
+ loadQueryInfluencers
+ );
}
protected String getSQLWhereString(String alias) {
@@ -1770,13 +1782,21 @@
}
}
- protected UniqueEntityLoader createEntityLoader(LockMode lockMode, Map enabledFilters)
throws MappingException {
+ protected UniqueEntityLoader createEntityLoader(
+ LockMode lockMode,
+ LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
//TODO: disable batch loading if lockMode > READ?
- return BatchingEntityLoader.createBatchingEntityLoader( this, batchSize, lockMode,
getFactory(), enabledFilters );
+ return BatchingEntityLoader.createBatchingEntityLoader(
+ this,
+ batchSize,
+ lockMode,
+ getFactory(),
+ loadQueryInfluencers
+ );
}
protected UniqueEntityLoader createEntityLoader(LockMode lockMode) throws
MappingException {
- return createEntityLoader( lockMode, CollectionHelper.EMPTY_MAP );
+ return createEntityLoader( lockMode, LoadQueryInfluencers.NONE );
}
protected boolean check(int rows, Serializable id, int tableNumber, Expectation
expectation, PreparedStatement statement) throws HibernateException {
@@ -3072,21 +3092,49 @@
return loader.load( id, optionalObject, session );
}
+ public void registerAffectingFetchProfile(String fetchProfileName) {
+ affectingFetchProfileNames.add( fetchProfileName );
+ }
+
+ private boolean isAffectedByEnabledFetchProfiles(SessionImplementor session) {
+ Iterator itr =
session.getLoadQueryInfluencers().getEnabledFetchProfileNames().iterator();
+ while ( itr.hasNext() ) {
+ if ( affectingFetchProfileNames.contains( itr.next() ) ) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isAffectedByEnabledFilters(SessionImplementor session) {
+ return session.getLoadQueryInfluencers().hasEnabledFilters()
+ && filterHelper.isAffectedBy(
session.getLoadQueryInfluencers().getEnabledFilters() );
+ }
+
private UniqueEntityLoader getAppropriateLoader(LockMode lockMode, SessionImplementor
session) {
- final Map enabledFilters = session.getEnabledFilters();
if ( queryLoader != null ) {
+ // if the user specified a custom query loader we need to that
+ // regardless of any other consideration
return queryLoader;
}
- else if ( enabledFilters == null || enabledFilters.isEmpty() ) {
- if ( session.getFetchProfile()!=null && LockMode.UPGRADE.greaterThan(lockMode)
) {
- return (UniqueEntityLoader) loaders.get( session.getFetchProfile() );
- }
- else {
- return (UniqueEntityLoader) loaders.get( lockMode );
- }
+ else if ( isAffectedByEnabledFilters( session ) ) {
+ // because filters affect the rows returned (because they add
+ // restirctions) these need to be next in precendence
+ return createEntityLoader( lockMode, session.getLoadQueryInfluencers() );
}
+ else if ( session.getLoadQueryInfluencers().getInternalFetchProfile() != null
&& LockMode.UPGRADE.greaterThan( lockMode ) ) {
+ // Next, we consider whether an 'internal' fetch profile has been set.
+ // This indicates a special fetch profile Hibernate needs applied
+ // (for its merge loading process e.g.).
+ return ( UniqueEntityLoader ) loaders.get(
session.getLoadQueryInfluencers().getInternalFetchProfile() );
+ }
+ else if ( isAffectedByEnabledFetchProfiles( session ) ) {
+ // If the session has associated influencers we need to adjust the
+ // SQL query used for loading based on those influencers
+ return createEntityLoader( lockMode, session.getLoadQueryInfluencers() );
+ }
else {
- return createEntityLoader( lockMode, enabledFilters );
+ return ( UniqueEntityLoader ) loaders.get( lockMode );
}
}
Modified: core/trunk/core/src/main/java/org/hibernate/persister/entity/Loadable.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/persister/entity/Loadable.java 2008-08-15
21:03:38 UTC (rev 15090)
+++ core/trunk/core/src/main/java/org/hibernate/persister/entity/Loadable.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -108,4 +108,12 @@
public boolean isAbstract();
+ /**
+ * Register the name of a fetch profile determined to have an affect on the
+ * underlying loadable in regards to the fact that the underlying load SQL
+ * needs to be adjust when the given fetch profile is enabled.
+ *
+ * @param fetchProfileName The name of the profile affecting this.
+ */
+ public void registerAffectingFetchProfile(String fetchProfileName);
}
Modified: core/trunk/core/src/main/resources/org/hibernate/hibernate-mapping-3.0.dtd
===================================================================
--- core/trunk/core/src/main/resources/org/hibernate/hibernate-mapping-3.0.dtd 2008-08-15
21:03:38 UTC (rev 15090)
+++ core/trunk/core/src/main/resources/org/hibernate/hibernate-mapping-3.0.dtd 2008-08-15
21:20:15 UTC (rev 15091)
@@ -19,11 +19,12 @@
<!ELEMENT hibernate-mapping (
meta*,
typedef*,
- import*,
+ import*,
(class|subclass|joined-subclass|union-subclass)*,
resultset*,
(query|sql-query)*,
filter-def*,
+ fetch-profile*,
database-object*
)>
<!ATTLIST hibernate-mapping schema CDATA #IMPLIED> <!-- default: none
-->
@@ -78,6 +79,7 @@
((join*,subclass*)|joined-subclass*|union-subclass*),
loader?,sql-insert?,sql-update?,sql-delete?,
filter*,
+ fetch-profile*,
resultset*,
(query|sql-query)*
)>
@@ -133,7 +135,23 @@
<!ATTLIST filter name CDATA #REQUIRED>
<!ATTLIST filter condition CDATA #IMPLIED>
+<!--
+-->
+<!ELEMENT fetch-profile (fetch*)>
+ <!ATTLIST fetch-profile name CDATA #REQUIRED>
+<!--
+ The <fetch> element defines a single path to which the fetch
+ refers, as well as the style of fetch to apply. The 'root' of the
+ path is different depending upon the context in which the
+ containing <fetch-profile/> occurs; within a <class/> element,
+ the entity-name of the containing class mapping is assumed...
+-->
+<!ELEMENT fetch EMPTY>
+ <!ATTLIST fetch entity CDATA #IMPLIED> <!-- Implied as long as the
containing fetch profile is contained in a class mapping -->
+ <!ATTLIST fetch association CDATA #REQUIRED>
+ <!ATTLIST fetch style (join|select) "join">
+
<!-- A join allows some properties of a class to be persisted to a second table
-->
<!ELEMENT join (
@@ -231,6 +249,7 @@
join*,
subclass*,
loader?,sql-insert?,sql-update?,sql-delete?,
+ fetch-profile*,
resultset*,
(query|sql-query)*
)>
@@ -263,6 +282,7 @@
(property|many-to-one|one-to-one|component|dynamic-component|properties|any|map|set|list|bag|idbag|array|primitive-array)*,
joined-subclass*,
loader?,sql-insert?,sql-update?,sql-delete?,
+ fetch-profile*,
resultset*,
(query|sql-query)*
)>
@@ -298,6 +318,7 @@
(property|many-to-one|one-to-one|component|dynamic-component|properties|any|map|set|list|bag|idbag|array|primitive-array)*,
union-subclass*,
loader?,sql-insert?,sql-update?,sql-delete?,
+ fetch-profile*,
resultset*,
(query|sql-query)*
)>
Modified: core/trunk/jmx/src/main/java/org/hibernate/jmx/SessionFactoryStub.java
===================================================================
--- core/trunk/jmx/src/main/java/org/hibernate/jmx/SessionFactoryStub.java 2008-08-15
21:03:38 UTC (rev 15090)
+++ core/trunk/jmx/src/main/java/org/hibernate/jmx/SessionFactoryStub.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -198,4 +198,8 @@
public FilterDefinition getFilterDefinition(String filterName) throws HibernateException
{
return getImpl().getFilterDefinition( filterName );
}
+
+ public boolean containsFetchProfileDefition(String name) {
+ return getImpl().containsFetchProfileDefition( name );
+ }
}
Added:
core/trunk/testsuite/src/test/java/org/hibernate/test/fetchprofiles/basic/BasicFetchProfileTest.java
===================================================================
---
core/trunk/testsuite/src/test/java/org/hibernate/test/fetchprofiles/basic/BasicFetchProfileTest.java
(rev 0)
+++
core/trunk/testsuite/src/test/java/org/hibernate/test/fetchprofiles/basic/BasicFetchProfileTest.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -0,0 +1,281 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC 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.
+ *
+ * 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.test.fetchprofiles.basic;
+
+import org.hibernate.junit.functional.FunctionalTestCase;
+import org.hibernate.Session;
+import org.hibernate.Hibernate;
+import org.hibernate.UnknownProfileException;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.engine.SessionImplementor;
+
+/**
+ * TODO : javadoc
+ *
+ * @author Steve Ebersole
+ */
+public class BasicFetchProfileTest extends FunctionalTestCase {
+ public BasicFetchProfileTest(String string) {
+ super( string );
+ }
+
+ public String[] getMappings() {
+ return new String[] { "fetchprofiles/basic/Mappings.hbm.xml" };
+ }
+
+ public String getCacheConcurrencyStrategy() {
+ return null;
+ }
+
+ public void configure(Configuration cfg) {
+ cfg.setProperty( Environment.GENERATE_STATISTICS, "true" );
+ }
+
+ private static interface TestData {
+ public Long getStudentId();
+ public Long getDepartmentId();
+ public Long getCourseId();
+ public Long getSectionId();
+ public Long getEnrollmentId();
+ }
+
+ private interface TestCode {
+ public void perform(TestData data);
+ }
+
+ private void performWithStandardData(TestCode testCode) {
+ Session session = openSession();
+ session.beginTransaction();
+ final Department literatureDepartment = new Department( "lit",
"Literature" );
+ session.save( literatureDepartment );
+ final Course lit101 = new Course( new Course.Code( literatureDepartment, 101 ),
"Introduction to Literature" );
+ session.save( lit101 );
+ final CourseOffering section = new CourseOffering( lit101, 1, 2008 );
+ session.save( section );
+ final Student me = new Student( "Steve" );
+ session.save( me );
+ final Enrollment enrollment = new Enrollment( section, me );
+ section.getEnrollments().add( enrollment );
+ session.save( enrollment );
+ session.getTransaction().commit();
+ session.close();
+
+ sfi().getStatistics().clear();
+
+ testCode.perform(
+ new TestData() {
+ public Long getStudentId() {
+ return me.getId();
+ }
+
+ public Long getDepartmentId() {
+ return literatureDepartment.getId();
+ }
+
+ public Long getCourseId() {
+ return lit101.getId();
+ }
+
+ public Long getSectionId() {
+ return section.getId();
+ }
+
+ public Long getEnrollmentId() {
+ return enrollment.getId();
+ }
+ }
+ );
+
+ session = openSession();
+ session.beginTransaction();
+ session.delete( enrollment );
+ session.delete( me );
+ session.delete( enrollment.getOffering() );
+ session.delete( enrollment.getOffering().getCourse() );
+ session.delete( enrollment.getOffering().getCourse().getCode().getDepartment() );
+ session.getTransaction().commit();
+ session.close();
+ }
+
+ public void testNormalLoading() {
+ performWithStandardData(
+ new TestCode() {
+ public void perform(TestData data) {
+ Session session = openSession();
+ session.beginTransaction();
+ CourseOffering section = ( CourseOffering ) session.get( CourseOffering.class,
data.getSectionId() );
+ assertEquals( 1, sfi().getStatistics().getEntityLoadCount() );
+ assertEquals( 0, sfi().getStatistics().getEntityFetchCount() );
+ assertFalse( Hibernate.isInitialized( section.getCourse() ) );
+ assertFalse( Hibernate.isInitialized( section.getEnrollments() ) );
+ assertFalse( Hibernate.isInitialized( section.getCourse().getCode().getDepartment()
) );
+ assertTrue( Hibernate.isInitialized( section.getCourse() ) );
+ assertEquals( 1, sfi().getStatistics().getEntityFetchCount() );
+ session.getTransaction().commit();
+ session.close();
+ }
+ }
+ );
+ }
+
+ public void testNormalCriteria() {
+ performWithStandardData(
+ new TestCode() {
+ public void perform(TestData data) {
+ Session session = openSession();
+ session.beginTransaction();
+ CourseOffering section = ( CourseOffering ) session.createCriteria(
CourseOffering.class ).uniqueResult();
+ assertEquals( 1, sfi().getStatistics().getEntityLoadCount() );
+ assertEquals( 0, sfi().getStatistics().getEntityFetchCount() );
+ assertFalse( Hibernate.isInitialized( section.getCourse() ) );
+ assertFalse( Hibernate.isInitialized( section.getEnrollments() ) );
+ assertFalse( Hibernate.isInitialized( section.getCourse().getCode().getDepartment()
) );
+ assertTrue( Hibernate.isInitialized( section.getCourse() ) );
+ assertEquals( 1, sfi().getStatistics().getEntityFetchCount() );
+ session.getTransaction().commit();
+ session.close();
+ }
+ }
+ );
+ }
+
+ public void testBasicFetchProfileOperation() {
+ assertTrue( "fetch profile not parsed properly",
sfi().containsFetchProfileDefition( "enrollment.details" ) );
+ assertTrue( "fetch profile not parsed properly",
sfi().containsFetchProfileDefition( "offering.details" ) );
+ assertTrue( "fetch profile not parsed properly",
sfi().containsFetchProfileDefition( "course.details" ) );
+ Session s = openSession();
+ SessionImplementor si = ( SessionImplementor ) s;
+ s.enableFetchProfile( "enrollment.details" );
+ assertTrue( si.getLoadQueryInfluencers().hasEnabledFetchProfiles() );
+ s.disableFetchProfile( "enrollment.details" );
+ assertFalse( si.getLoadQueryInfluencers().hasEnabledFetchProfiles() );
+ try {
+ s.enableFetchProfile( "never-gonna-get-it" );
+ fail( "expecting failure on undefined fetch-profile" );
+ }
+ catch ( UnknownProfileException expected ) {
+ }
+ s.close();
+ }
+
+ public void testLoadManyToOneFetchProfile() {
+ performWithStandardData(
+ new TestCode() {
+ public void perform(TestData data) {
+ Session session = openSession();
+ session.beginTransaction();
+ session.enableFetchProfile( "enrollment.details" );
+ Enrollment enrollment = ( Enrollment ) session.get( Enrollment.class,
data.getEnrollmentId() );
+ assertEquals( 3, sfi().getStatistics().getEntityLoadCount() ); // enrollment +
(section + student)
+ assertEquals( 0, sfi().getStatistics().getEntityFetchCount() );
+ assertTrue( Hibernate.isInitialized( enrollment.getOffering() ) );
+ assertTrue( Hibernate.isInitialized( enrollment.getStudent() ) );
+ assertEquals( 0, sfi().getStatistics().getEntityFetchCount() );
+ session.getTransaction().commit();
+ session.close();
+ }
+ }
+ );
+ }
+
+ public void testCriteriaManyToOneFetchProfile() {
+ performWithStandardData(
+ new TestCode() {
+ public void perform(TestData data) {
+ Session session = openSession();
+ session.beginTransaction();
+ session.enableFetchProfile( "enrollment.details" );
+ Enrollment enrollment = ( Enrollment ) session.createCriteria( Enrollment.class
).uniqueResult();
+ assertEquals( 3, sfi().getStatistics().getEntityLoadCount() ); // enrollment +
(section + student)
+ assertEquals( 0, sfi().getStatistics().getEntityFetchCount() );
+ assertTrue( Hibernate.isInitialized( enrollment.getOffering() ) );
+ assertTrue( Hibernate.isInitialized( enrollment.getStudent() ) );
+ assertEquals( 0, sfi().getStatistics().getEntityFetchCount() );
+ session.getTransaction().commit();
+ session.close();
+ }
+ }
+ );
+ }
+
+ public void testLoadOneToManyFetchProfile() {
+ performWithStandardData(
+ new TestCode() {
+ public void perform(TestData data) {
+ Session session = openSession();
+ session.beginTransaction();
+ session.enableFetchProfile( "offering.details" );
+ CourseOffering section = ( CourseOffering ) session.get( CourseOffering.class,
data.getSectionId() );
+ assertEquals( 3, sfi().getStatistics().getEntityLoadCount() ); // section +
(enrollments + course)
+ assertEquals( 0, sfi().getStatistics().getEntityFetchCount() );
+ assertTrue( Hibernate.isInitialized( section.getEnrollments() ) );
+ session.getTransaction().commit();
+ session.close();
+ }
+ }
+ );
+ }
+
+ public void testLoadDeepFetchProfile() {
+ performWithStandardData(
+ new TestCode() {
+ public void perform(TestData data) {
+ Session session = openSession();
+ session.beginTransaction();
+ // enable both enrollment and offering detail profiles;
+ // then loading the section/offering should fetch the enrollment
+ // which in turn should fetch student (+ offering).
+ session.enableFetchProfile( "offering.details" );
+ session.enableFetchProfile( "enrollment.details" );
+ CourseOffering section = ( CourseOffering ) session.get( CourseOffering.class,
data.getSectionId() );
+ assertEquals( 4, sfi().getStatistics().getEntityLoadCount() ); // section + (course
+ enrollments + (student))
+ assertEquals( 0, sfi().getStatistics().getEntityFetchCount() );
+ assertTrue( Hibernate.isInitialized( section.getEnrollments() ) );
+ session.getTransaction().commit();
+ session.close();
+ }
+ }
+ );
+ }
+
+ public void testLoadComponentDerefFetchProfile() {
+ performWithStandardData(
+ new TestCode() {
+ public void perform(TestData data) {
+ Session session = openSession();
+ session.beginTransaction();
+ session.enableFetchProfile( "course.details" );
+ Course course = ( Course ) session.get( Course.class, data.getCourseId() );
+ assertEquals( 2, sfi().getStatistics().getEntityLoadCount() ); // course +
department
+ assertEquals( 0, sfi().getStatistics().getEntityFetchCount() );
+ assertTrue( Hibernate.isInitialized( course.getCode().getDepartment() ) );
+ session.getTransaction().commit();
+ session.close();
+ }
+ }
+ );
+ }
+}
Added:
core/trunk/testsuite/src/test/java/org/hibernate/test/fetchprofiles/basic/Course.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/fetchprofiles/basic/Course.java
(rev 0)
+++
core/trunk/testsuite/src/test/java/org/hibernate/test/fetchprofiles/basic/Course.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -0,0 +1,123 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC 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.
+ *
+ * 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.test.fetchprofiles.basic;
+
+/**
+ * TODO : javadoc
+ *
+ * @author Steve Ebersole
+ */
+public class Course {
+ private Long id;
+ private Code code;
+ private String name;
+
+ public Course() {
+ }
+
+ public Course(Code code, String name) {
+ this.code = code;
+ this.name = name;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public Code getCode() {
+ return code;
+ }
+
+ public void setCode(Code code) {
+ this.code = code;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+ public static class Code {
+ private Department department;
+ private int number;
+
+ public Code() {
+ }
+
+ public Code(Department department, int number) {
+ this.department = department;
+ this.number = number;
+ }
+
+ public Department getDepartment() {
+ return department;
+ }
+
+ public void setDepartment(Department department) {
+ this.department = department;
+ }
+
+ public int getNumber() {
+ return number;
+ }
+
+ public void setNumber(int number) {
+ this.number = number;
+ }
+
+ public boolean equals(Object o) {
+ if ( this == o ) {
+ return true;
+ }
+ if ( !( o instanceof Code ) ) {
+ return false;
+ }
+
+ Code code = ( Code ) o;
+
+ if ( number != code.number ) {
+ return false;
+ }
+ if ( !department.equals( code.department ) ) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = department.hashCode();
+ result = 31 * result + number;
+ return result;
+ }
+ }
+}
Added:
core/trunk/testsuite/src/test/java/org/hibernate/test/fetchprofiles/basic/CourseOffering.java
===================================================================
---
core/trunk/testsuite/src/test/java/org/hibernate/test/fetchprofiles/basic/CourseOffering.java
(rev 0)
+++
core/trunk/testsuite/src/test/java/org/hibernate/test/fetchprofiles/basic/CourseOffering.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -0,0 +1,90 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC 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.
+ *
+ * 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.test.fetchprofiles.basic;
+
+import java.util.Set;
+import java.util.HashSet;
+
+/**
+ * TODO : javadoc
+ *
+ * @author Steve Ebersole
+ */
+public class CourseOffering {
+ private Long id;
+ private Course course;
+ private int semester;
+ private int year;
+ private Set enrollments = new HashSet();
+
+ public CourseOffering() {
+ }
+
+ public CourseOffering(Course course, int semester, int year) {
+ this.course = course;
+ this.semester = semester;
+ this.year = year;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public Course getCourse() {
+ return course;
+ }
+
+ public void setCourse(Course course) {
+ this.course = course;
+ }
+
+ public int getSemester() {
+ return semester;
+ }
+
+ public void setSemester(int semester) {
+ this.semester = semester;
+ }
+
+ public int getYear() {
+ return year;
+ }
+
+ public void setYear(int year) {
+ this.year = year;
+ }
+
+ public Set getEnrollments() {
+ return enrollments;
+ }
+
+ public void setEnrollments(Set enrollments) {
+ this.enrollments = enrollments;
+ }
+}
Added:
core/trunk/testsuite/src/test/java/org/hibernate/test/fetchprofiles/basic/Department.java
===================================================================
---
core/trunk/testsuite/src/test/java/org/hibernate/test/fetchprofiles/basic/Department.java
(rev 0)
+++
core/trunk/testsuite/src/test/java/org/hibernate/test/fetchprofiles/basic/Department.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -0,0 +1,68 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC 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.
+ *
+ * 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.test.fetchprofiles.basic;
+
+/**
+ * TODO : javadoc
+ *
+ * @author Steve Ebersole
+ */
+public class Department {
+ private Long id;
+ private String code;
+ private String name;
+
+ public Department() {
+ }
+
+ public Department(String code, String name) {
+ this.code = code;
+ this.name = name;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
Added:
core/trunk/testsuite/src/test/java/org/hibernate/test/fetchprofiles/basic/Enrollment.java
===================================================================
---
core/trunk/testsuite/src/test/java/org/hibernate/test/fetchprofiles/basic/Enrollment.java
(rev 0)
+++
core/trunk/testsuite/src/test/java/org/hibernate/test/fetchprofiles/basic/Enrollment.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -0,0 +1,77 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC 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.
+ *
+ * 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.test.fetchprofiles.basic;
+
+/**
+ * TODO : javadoc
+ *
+ * @author Steve Ebersole
+ */
+public class Enrollment {
+ private Long id;
+ private CourseOffering offering;
+ private Student student;
+ private int finalGrade;
+
+ public Enrollment() {
+ }
+
+ public Enrollment(CourseOffering offering, Student student) {
+ this.offering = offering;
+ this.student = student;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public CourseOffering getOffering() {
+ return offering;
+ }
+
+ public void setOffering(CourseOffering offering) {
+ this.offering = offering;
+ }
+
+ public Student getStudent() {
+ return student;
+ }
+
+ public void setStudent(Student student) {
+ this.student = student;
+ }
+
+ public int getFinalGrade() {
+ return finalGrade;
+ }
+
+ public void setFinalGrade(int finalGrade) {
+ this.finalGrade = finalGrade;
+ }
+}
Added:
core/trunk/testsuite/src/test/java/org/hibernate/test/fetchprofiles/basic/Mappings.hbm.xml
===================================================================
---
core/trunk/testsuite/src/test/java/org/hibernate/test/fetchprofiles/basic/Mappings.hbm.xml
(rev 0)
+++
core/trunk/testsuite/src/test/java/org/hibernate/test/fetchprofiles/basic/Mappings.hbm.xml 2008-08-15
21:20:15 UTC (rev 15091)
@@ -0,0 +1,96 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping
+ SYSTEM
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
+
+<!--
+ ~ Hibernate, Relational Persistence for Idiomatic Java
+ ~
+ ~ Copyright (c) 2008, Red Hat Middleware LLC 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.
+ ~
+ ~ 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
+ ~
+ -->
+
+<hibernate-mapping package="org.hibernate.test.fetchprofiles.basic">
+
+ <class name="Department">
+ <id name="id" type="long">
+ <generator class="increment"/>
+ </id>
+ <property name="code" column="CODE"
type="string"/>
+ <property name="name" column="NAME"
type="string"/>
+ </class>
+
+ <class name="Student">
+ <id name="id" type="long">
+ <generator class="increment"/>
+ </id>
+ <property name="name" column="NAME"
type="string"/>
+ </class>
+
+ <class name="Course">
+ <id name="id" type="long">
+ <generator class="increment"/>
+ </id>
+ <property name="name" column="NAME"
type="string"/>
+ <component name="code" class="Course$Code">
+ <many-to-one name="department" class="Department"
column="DEPT_ID" cascade="save-update"/>
+ <property name="number" type="int"
column="CODE_NUMBER"/>
+ </component>
+ <fetch-profile name="course.details">
+ <fetch association="code.department"
style="join"/>
+ </fetch-profile>
+ </class>
+
+ <class name="CourseOffering" table="SECTION">
+ <id name="id" type="long">
+ <generator class="increment"/>
+ </id>
+ <many-to-one name="course" column="COURSE_ID"
class="Course"/>
+ <property name="semester" type="int"
column="SEMESTER"/>
+ <property name="year" type="int"
column="YEAR"/>
+ <set name="enrollments" lazy="true"
cascade="all">
+ <key column="SECTION_ID"/>
+ <one-to-many class="Enrollment"/>
+ </set>
+ <fetch-profile name="offering.details">
+ <fetch association="enrollments" style="join"/>
+ <fetch association="course" style="join"/>
+ </fetch-profile>
+ <fetch-profile name="offering.details2">
+ <fetch entity="CourseOffering"
association="enrollments" style="join"/>
+ </fetch-profile>
+ </class>
+
+ <class name="Enrollment">
+ <id name="id" type="long">
+ <generator class="increment"/>
+ </id>
+ <many-to-one name="offering" column="SECTION_ID"
class="CourseOffering" cascade="none"/>
+ <many-to-one name="student" column="STUDENT_ID"
class="Student" cascade="none"/>
+ <property name="finalGrade" column="FINAL_GRADE"
type="int"/>
+ </class>
+
+ <fetch-profile name="enrollment.details">
+ <fetch entity="Enrollment" association="student"
style="join"/>
+ <fetch entity="Enrollment" association="offering"
style="join"/>
+ </fetch-profile>
+
+</hibernate-mapping>
Added:
core/trunk/testsuite/src/test/java/org/hibernate/test/fetchprofiles/basic/Student.java
===================================================================
---
core/trunk/testsuite/src/test/java/org/hibernate/test/fetchprofiles/basic/Student.java
(rev 0)
+++
core/trunk/testsuite/src/test/java/org/hibernate/test/fetchprofiles/basic/Student.java 2008-08-15
21:20:15 UTC (rev 15091)
@@ -0,0 +1,58 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC 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.
+ *
+ * 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.test.fetchprofiles.basic;
+
+/**
+ * TODO : javadoc
+ *
+ * @author Steve Ebersole
+ */
+public class Student {
+ private Long id;
+ private String name;
+
+ public Student() {
+ }
+
+ public Student(String name) {
+ this.name = name;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
Modified: core/trunk/testsuite/src/test/resources/hibernate.properties
===================================================================
--- core/trunk/testsuite/src/test/resources/hibernate.properties 2008-08-15 21:03:38 UTC
(rev 15090)
+++ core/trunk/testsuite/src/test/resources/hibernate.properties 2008-08-15 21:20:15 UTC
(rev 15091)
@@ -22,6 +22,7 @@
hibernate.connection.pool_size 5
+hibernate.show_sql true
hibernate.format_sql true
hibernate.max_fetch_depth 5