HHH-3414 : fetch profiles, phase 1 : join fetching
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@15091 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
8f3ce7a6e7
commit
fbae6db0ab
|
@ -813,4 +813,40 @@ public interface Session extends Serializable {
|
||||||
* @see #disconnect()
|
* @see #disconnect()
|
||||||
*/
|
*/
|
||||||
void reconnect(Connection connection) throws HibernateException;
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -244,4 +244,13 @@ public interface SessionFactory extends Referenceable, Serializable {
|
||||||
* @throws HibernateException If no filter defined with the given name.
|
* @throws HibernateException If no filter defined with the given name.
|
||||||
*/
|
*/
|
||||||
public FilterDefinition getFilterDefinition(String filterName) throws HibernateException;
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -114,6 +114,7 @@ import org.hibernate.mapping.RootClass;
|
||||||
import org.hibernate.mapping.SimpleValue;
|
import org.hibernate.mapping.SimpleValue;
|
||||||
import org.hibernate.mapping.Table;
|
import org.hibernate.mapping.Table;
|
||||||
import org.hibernate.mapping.UniqueKey;
|
import org.hibernate.mapping.UniqueKey;
|
||||||
|
import org.hibernate.mapping.FetchProfile;
|
||||||
import org.hibernate.proxy.EntityNotFoundDelegate;
|
import org.hibernate.proxy.EntityNotFoundDelegate;
|
||||||
import org.hibernate.secure.JACCConfiguration;
|
import org.hibernate.secure.JACCConfiguration;
|
||||||
import org.hibernate.tool.hbm2ddl.DatabaseMetadata;
|
import org.hibernate.tool.hbm2ddl.DatabaseMetadata;
|
||||||
|
@ -163,6 +164,7 @@ public class Configuration implements Serializable {
|
||||||
*/
|
*/
|
||||||
protected Map sqlResultSetMappings;
|
protected Map sqlResultSetMappings;
|
||||||
protected Map filterDefinitions;
|
protected Map filterDefinitions;
|
||||||
|
protected Map fetchProfiles;
|
||||||
protected List secondPasses;
|
protected List secondPasses;
|
||||||
protected List propertyReferences;
|
protected List propertyReferences;
|
||||||
// protected List extendsQueue;
|
// protected List extendsQueue;
|
||||||
|
@ -202,6 +204,7 @@ public class Configuration implements Serializable {
|
||||||
entityResolver = XMLHelper.DEFAULT_DTD_RESOLVER;
|
entityResolver = XMLHelper.DEFAULT_DTD_RESOLVER;
|
||||||
eventListeners = new EventListeners();
|
eventListeners = new EventListeners();
|
||||||
filterDefinitions = new HashMap();
|
filterDefinitions = new HashMap();
|
||||||
|
fetchProfiles = new HashMap();
|
||||||
// extendsQueue = new ArrayList();
|
// extendsQueue = new ArrayList();
|
||||||
extendsQueue = new HashMap();
|
extendsQueue = new HashMap();
|
||||||
auxiliaryDatabaseObjects = new ArrayList();
|
auxiliaryDatabaseObjects = new ArrayList();
|
||||||
|
@ -720,6 +723,7 @@ public class Configuration implements Serializable {
|
||||||
namingStrategy,
|
namingStrategy,
|
||||||
typeDefs,
|
typeDefs,
|
||||||
filterDefinitions,
|
filterDefinitions,
|
||||||
|
fetchProfiles,
|
||||||
extendsQueue,
|
extendsQueue,
|
||||||
auxiliaryDatabaseObjects,
|
auxiliaryDatabaseObjects,
|
||||||
tableNameBinding,
|
tableNameBinding,
|
||||||
|
@ -2181,6 +2185,14 @@ public class Configuration implements Serializable {
|
||||||
filterDefinitions.put( definition.getFilterName(), definition );
|
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) {
|
public void addAuxiliaryDatabaseObject(AuxiliaryDatabaseObject object) {
|
||||||
auxiliaryDatabaseObjects.add( object );
|
auxiliaryDatabaseObjects.add( object );
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,6 +89,7 @@ import org.hibernate.mapping.TypeDef;
|
||||||
import org.hibernate.mapping.UnionSubclass;
|
import org.hibernate.mapping.UnionSubclass;
|
||||||
import org.hibernate.mapping.UniqueKey;
|
import org.hibernate.mapping.UniqueKey;
|
||||||
import org.hibernate.mapping.Value;
|
import org.hibernate.mapping.Value;
|
||||||
|
import org.hibernate.mapping.FetchProfile;
|
||||||
import org.hibernate.persister.entity.JoinedSubclassEntityPersister;
|
import org.hibernate.persister.entity.JoinedSubclassEntityPersister;
|
||||||
import org.hibernate.persister.entity.SingleTableEntityPersister;
|
import org.hibernate.persister.entity.SingleTableEntityPersister;
|
||||||
import org.hibernate.persister.entity.UnionSubclassEntityPersister;
|
import org.hibernate.persister.entity.UnionSubclassEntityPersister;
|
||||||
|
@ -158,6 +159,9 @@ public final class HbmBinder {
|
||||||
if ( "filter-def".equals( elementName ) ) {
|
if ( "filter-def".equals( elementName ) ) {
|
||||||
parseFilterDef( element, mappings );
|
parseFilterDef( element, mappings );
|
||||||
}
|
}
|
||||||
|
else if ( "fetch-profile".equals( elementName ) ) {
|
||||||
|
parseFetchProfile( element, mappings, null );
|
||||||
|
}
|
||||||
else if ( "typedef".equals( elementName ) ) {
|
else if ( "typedef".equals( elementName ) ) {
|
||||||
bindTypeDef( element, mappings );
|
bindTypeDef( element, mappings );
|
||||||
}
|
}
|
||||||
|
@ -546,8 +550,13 @@ public final class HbmBinder {
|
||||||
bindDom4jRepresentation( node, persistentClass, mappings, inheritedMetas );
|
bindDom4jRepresentation( node, persistentClass, mappings, inheritedMetas );
|
||||||
bindMapRepresentation( node, persistentClass, mappings, inheritedMetas );
|
bindMapRepresentation( node, persistentClass, mappings, inheritedMetas );
|
||||||
|
|
||||||
bindPersistentClassCommonValues( 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,
|
private static void bindPojoRepresentation(Element node, PersistentClass entity,
|
||||||
|
@ -2963,6 +2972,25 @@ public final class HbmBinder {
|
||||||
filterable.addFilter( name, condition );
|
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) {
|
private static String getSubselect(Element element) {
|
||||||
String subselect = element.attributeValue( "subselect" );
|
String subselect = element.attributeValue( "subselect" );
|
||||||
if ( subselect != null ) {
|
if ( subselect != null ) {
|
||||||
|
|
|
@ -46,6 +46,7 @@ import org.hibernate.mapping.Table;
|
||||||
import org.hibernate.mapping.TypeDef;
|
import org.hibernate.mapping.TypeDef;
|
||||||
import org.hibernate.mapping.AuxiliaryDatabaseObject;
|
import org.hibernate.mapping.AuxiliaryDatabaseObject;
|
||||||
import org.hibernate.mapping.Column;
|
import org.hibernate.mapping.Column;
|
||||||
|
import org.hibernate.mapping.FetchProfile;
|
||||||
import org.hibernate.util.StringHelper;
|
import org.hibernate.util.StringHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -77,6 +78,7 @@ public class Mappings implements Serializable {
|
||||||
protected final List propertyReferences;
|
protected final List propertyReferences;
|
||||||
protected final NamingStrategy namingStrategy;
|
protected final NamingStrategy namingStrategy;
|
||||||
protected final Map filterDefinitions;
|
protected final Map filterDefinitions;
|
||||||
|
protected final Map fetchProfiles;
|
||||||
protected final List auxiliaryDatabaseObjects;
|
protected final List auxiliaryDatabaseObjects;
|
||||||
|
|
||||||
protected final Map extendsQueue;
|
protected final Map extendsQueue;
|
||||||
|
@ -111,12 +113,12 @@ public class Mappings implements Serializable {
|
||||||
final NamingStrategy namingStrategy,
|
final NamingStrategy namingStrategy,
|
||||||
final Map typeDefs,
|
final Map typeDefs,
|
||||||
final Map filterDefinitions,
|
final Map filterDefinitions,
|
||||||
|
final Map fetchProfiles,
|
||||||
// final List extendsQueue,
|
// final List extendsQueue,
|
||||||
final Map extendsQueue,
|
final Map extendsQueue,
|
||||||
final List auxiliaryDatabaseObjects,
|
final List auxiliaryDatabaseObjects,
|
||||||
final Map tableNamebinding,
|
final Map tableNamebinding,
|
||||||
final Map columnNameBindingPerTable
|
final Map columnNameBindingPerTable) {
|
||||||
) {
|
|
||||||
this.classes = classes;
|
this.classes = classes;
|
||||||
this.collections = collections;
|
this.collections = collections;
|
||||||
this.queries = queries;
|
this.queries = queries;
|
||||||
|
@ -129,6 +131,7 @@ public class Mappings implements Serializable {
|
||||||
this.namingStrategy = namingStrategy;
|
this.namingStrategy = namingStrategy;
|
||||||
this.typeDefs = typeDefs;
|
this.typeDefs = typeDefs;
|
||||||
this.filterDefinitions = filterDefinitions;
|
this.filterDefinitions = filterDefinitions;
|
||||||
|
this.fetchProfiles = fetchProfiles;
|
||||||
this.extendsQueue = extendsQueue;
|
this.extendsQueue = extendsQueue;
|
||||||
this.auxiliaryDatabaseObjects = auxiliaryDatabaseObjects;
|
this.auxiliaryDatabaseObjects = auxiliaryDatabaseObjects;
|
||||||
this.tableNameBinding = tableNamebinding;
|
this.tableNameBinding = tableNamebinding;
|
||||||
|
@ -418,7 +421,20 @@ public class Mappings implements Serializable {
|
||||||
public FilterDefinition getFilterDefinition(String name) {
|
public FilterDefinition getFilterDefinition(String name) {
|
||||||
return (FilterDefinition) filterDefinitions.get(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() {
|
public boolean isDefaultLazy() {
|
||||||
return defaultLazy;
|
return defaultLazy;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ import org.hibernate.HibernateException;
|
||||||
import org.hibernate.engine.QueryParameters;
|
import org.hibernate.engine.QueryParameters;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.TypedValue;
|
import org.hibernate.engine.TypedValue;
|
||||||
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
import org.hibernate.impl.CriteriaImpl;
|
import org.hibernate.impl.CriteriaImpl;
|
||||||
import org.hibernate.loader.criteria.CriteriaJoinWalker;
|
import org.hibernate.loader.criteria.CriteriaJoinWalker;
|
||||||
import org.hibernate.loader.criteria.CriteriaQueryTranslator;
|
import org.hibernate.loader.criteria.CriteriaQueryTranslator;
|
||||||
|
@ -76,8 +77,9 @@ public abstract class SubqueryExpression implements Criterion {
|
||||||
factory,
|
factory,
|
||||||
criteriaImpl,
|
criteriaImpl,
|
||||||
criteriaImpl.getEntityOrClassName(),
|
criteriaImpl.getEntityOrClassName(),
|
||||||
new HashMap(),
|
LoadQueryInfluencers.NONE,
|
||||||
innerQuery.getRootSQLALias());
|
innerQuery.getRootSQLALias()
|
||||||
|
);
|
||||||
|
|
||||||
String sql = walker.getSQLString();
|
String sql = walker.getSQLString();
|
||||||
|
|
||||||
|
|
|
@ -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 );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -37,6 +37,7 @@ import org.hibernate.SessionFactory;
|
||||||
import org.hibernate.ConnectionReleaseMode;
|
import org.hibernate.ConnectionReleaseMode;
|
||||||
import org.hibernate.proxy.EntityNotFoundDelegate;
|
import org.hibernate.proxy.EntityNotFoundDelegate;
|
||||||
import org.hibernate.engine.query.QueryPlanCache;
|
import org.hibernate.engine.query.QueryPlanCache;
|
||||||
|
import org.hibernate.engine.profile.FetchProfile;
|
||||||
import org.hibernate.persister.collection.CollectionPersister;
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.cache.QueryCache;
|
import org.hibernate.cache.QueryCache;
|
||||||
|
@ -219,5 +220,13 @@ public interface SessionFactoryImplementor extends Mapping, SessionFactory {
|
||||||
public EntityNotFoundDelegate getEntityNotFoundDelegate();
|
public EntityNotFoundDelegate getEntityNotFoundDelegate();
|
||||||
|
|
||||||
public SQLFunctionRegistry getSqlFunctionRegistry();
|
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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ import java.sql.Connection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.hibernate.CacheMode;
|
import org.hibernate.CacheMode;
|
||||||
import org.hibernate.EntityMode;
|
import org.hibernate.EntityMode;
|
||||||
|
@ -237,6 +238,7 @@ public interface SessionImplementor extends Serializable {
|
||||||
* @param filterParameterName The filter parameter name in the format
|
* @param filterParameterName The filter parameter name in the format
|
||||||
* {FILTER_NAME.PARAMETER_NAME}.
|
* {FILTER_NAME.PARAMETER_NAME}.
|
||||||
* @return The filter parameter value.
|
* @return The filter parameter value.
|
||||||
|
* @deprecated use #getLoadQueryInfluencers instead
|
||||||
*/
|
*/
|
||||||
public Object getFilterParameterValue(String filterParameterName);
|
public Object getFilterParameterValue(String filterParameterName);
|
||||||
|
|
||||||
|
@ -245,6 +247,8 @@ public interface SessionImplementor extends Serializable {
|
||||||
*
|
*
|
||||||
* @param filterParameterName The filter parameter name in the format
|
* @param filterParameterName The filter parameter name in the format
|
||||||
* {FILTER_NAME.PARAMETER_NAME}.
|
* {FILTER_NAME.PARAMETER_NAME}.
|
||||||
|
* @return The filter param type
|
||||||
|
* @deprecated use #getLoadQueryInfluencers instead
|
||||||
*/
|
*/
|
||||||
public Type getFilterParameterType(String filterParameterName);
|
public Type getFilterParameterType(String filterParameterName);
|
||||||
|
|
||||||
|
@ -253,6 +257,7 @@ public interface SessionImplementor extends Serializable {
|
||||||
* name, with values corresponding to the {@link org.hibernate.impl.FilterImpl}
|
* name, with values corresponding to the {@link org.hibernate.impl.FilterImpl}
|
||||||
* instance.
|
* instance.
|
||||||
* @return The currently enabled filters.
|
* @return The currently enabled filters.
|
||||||
|
* @deprecated use #getLoadQueryInfluencers instead
|
||||||
*/
|
*/
|
||||||
public Map getEnabledFilters();
|
public Map getEnabledFilters();
|
||||||
|
|
||||||
|
@ -307,10 +312,22 @@ public interface SessionImplementor extends Serializable {
|
||||||
|
|
||||||
public void afterScrollOperation();
|
public void afterScrollOperation();
|
||||||
|
|
||||||
public void setFetchProfile(String name);
|
/**
|
||||||
|
* 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();
|
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 JDBCContext getJDBCContext();
|
public JDBCContext getJDBCContext();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -322,4 +339,12 @@ public interface SessionImplementor extends Serializable {
|
||||||
* @return True if the session is closed; false otherwise.
|
* @return True if the session is closed; false otherwise.
|
||||||
*/
|
*/
|
||||||
public boolean isClosed();
|
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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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() + "}]";
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -84,6 +84,9 @@ import org.hibernate.engine.NamedQueryDefinition;
|
||||||
import org.hibernate.engine.NamedSQLQueryDefinition;
|
import org.hibernate.engine.NamedSQLQueryDefinition;
|
||||||
import org.hibernate.engine.ResultSetMappingDefinition;
|
import org.hibernate.engine.ResultSetMappingDefinition;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
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.QueryPlanCache;
|
||||||
import org.hibernate.engine.query.sql.NativeSQLQuerySpecification;
|
import org.hibernate.engine.query.sql.NativeSQLQuerySpecification;
|
||||||
import org.hibernate.event.EventListeners;
|
import org.hibernate.event.EventListeners;
|
||||||
|
@ -100,6 +103,7 @@ import org.hibernate.persister.PersisterFactory;
|
||||||
import org.hibernate.persister.collection.CollectionPersister;
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.persister.entity.Queryable;
|
import org.hibernate.persister.entity.Queryable;
|
||||||
|
import org.hibernate.persister.entity.Loadable;
|
||||||
import org.hibernate.pretty.MessageHelper;
|
import org.hibernate.pretty.MessageHelper;
|
||||||
import org.hibernate.proxy.EntityNotFoundDelegate;
|
import org.hibernate.proxy.EntityNotFoundDelegate;
|
||||||
import org.hibernate.stat.Statistics;
|
import org.hibernate.stat.Statistics;
|
||||||
|
@ -156,6 +160,7 @@ public final class SessionFactoryImpl implements SessionFactory, SessionFactoryI
|
||||||
private final transient Map namedSqlQueries;
|
private final transient Map namedSqlQueries;
|
||||||
private final transient Map sqlResultSetMappings;
|
private final transient Map sqlResultSetMappings;
|
||||||
private final transient Map filters;
|
private final transient Map filters;
|
||||||
|
private final transient Map fetchProfiles;
|
||||||
private final transient Map imports;
|
private final transient Map imports;
|
||||||
private final transient Interceptor interceptor;
|
private final transient Interceptor interceptor;
|
||||||
private final transient Settings settings;
|
private final transient Settings settings;
|
||||||
|
@ -198,6 +203,7 @@ public final class SessionFactoryImpl implements SessionFactory, SessionFactoryI
|
||||||
public void sessionFactoryClosed(SessionFactory factory) {
|
public void sessionFactoryClosed(SessionFactory factory) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.filters = new HashMap();
|
this.filters = new HashMap();
|
||||||
this.filters.putAll( cfg.getFilterDefinitions() );
|
this.filters.putAll( cfg.getFilterDefinitions() );
|
||||||
|
|
||||||
|
@ -412,6 +418,43 @@ public final class SessionFactoryImpl implements SessionFactory, SessionFactoryI
|
||||||
}
|
}
|
||||||
this.entityNotFoundDelegate = entityNotFoundDelegate;
|
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 );
|
this.observer.sessionFactoryCreated( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1004,6 +1047,10 @@ public final class SessionFactoryImpl implements SessionFactory, SessionFactoryI
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean containsFetchProfileDefition(String name) {
|
||||||
|
return fetchProfiles.containsKey( name );
|
||||||
|
}
|
||||||
|
|
||||||
public Set getDefinedFilterNames() {
|
public Set getDefinedFilterNames() {
|
||||||
return filters.keySet();
|
return filters.keySet();
|
||||||
}
|
}
|
||||||
|
@ -1061,6 +1108,14 @@ public final class SessionFactoryImpl implements SessionFactory, SessionFactoryI
|
||||||
return entityNotFoundDelegate;
|
return entityNotFoundDelegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SQLFunctionRegistry getSqlFunctionRegistry() {
|
||||||
|
return sqlFunctionRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FetchProfile getFetchProfile(String name) {
|
||||||
|
return ( FetchProfile ) fetchProfiles.get( name );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom serialization hook used during Session serialization.
|
* Custom serialization hook used during Session serialization.
|
||||||
*
|
*
|
||||||
|
@ -1102,8 +1157,4 @@ public final class SessionFactoryImpl implements SessionFactory, SessionFactoryI
|
||||||
}
|
}
|
||||||
return ( SessionFactoryImpl ) result;
|
return ( SessionFactoryImpl ) result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SQLFunctionRegistry getSqlFunctionRegistry() {
|
|
||||||
return sqlFunctionRegistry;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,7 @@ import org.hibernate.SessionFactory;
|
||||||
import org.hibernate.Transaction;
|
import org.hibernate.Transaction;
|
||||||
import org.hibernate.TransientObjectException;
|
import org.hibernate.TransientObjectException;
|
||||||
import org.hibernate.UnresolvableObjectException;
|
import org.hibernate.UnresolvableObjectException;
|
||||||
|
import org.hibernate.UnknownProfileException;
|
||||||
import org.hibernate.collection.PersistentCollection;
|
import org.hibernate.collection.PersistentCollection;
|
||||||
import org.hibernate.engine.ActionQueue;
|
import org.hibernate.engine.ActionQueue;
|
||||||
import org.hibernate.engine.CollectionEntry;
|
import org.hibernate.engine.CollectionEntry;
|
||||||
|
@ -76,6 +77,7 @@ import org.hibernate.engine.PersistenceContext;
|
||||||
import org.hibernate.engine.QueryParameters;
|
import org.hibernate.engine.QueryParameters;
|
||||||
import org.hibernate.engine.StatefulPersistenceContext;
|
import org.hibernate.engine.StatefulPersistenceContext;
|
||||||
import org.hibernate.engine.Status;
|
import org.hibernate.engine.Status;
|
||||||
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
import org.hibernate.engine.query.FilterQueryPlan;
|
import org.hibernate.engine.query.FilterQueryPlan;
|
||||||
import org.hibernate.engine.query.HQLQueryPlan;
|
import org.hibernate.engine.query.HQLQueryPlan;
|
||||||
import org.hibernate.engine.query.NativeSQLQueryPlan;
|
import org.hibernate.engine.query.NativeSQLQueryPlan;
|
||||||
|
@ -167,10 +169,8 @@ public final class SessionImpl extends AbstractSessionImpl
|
||||||
private transient boolean flushBeforeCompletionEnabled;
|
private transient boolean flushBeforeCompletionEnabled;
|
||||||
private transient boolean autoCloseSessionEnabled;
|
private transient boolean autoCloseSessionEnabled;
|
||||||
private transient ConnectionReleaseMode connectionReleaseMode;
|
private transient ConnectionReleaseMode connectionReleaseMode;
|
||||||
|
|
||||||
private transient String fetchProfile;
|
|
||||||
|
|
||||||
private transient Map enabledFilters = new HashMap();
|
private transient LoadQueryInfluencers loadQueryInfluencers;
|
||||||
|
|
||||||
private transient Session rootSession;
|
private transient Session rootSession;
|
||||||
private transient Map childSessionsByEntityMode;
|
private transient Map childSessionsByEntityMode;
|
||||||
|
@ -195,6 +195,8 @@ public final class SessionImpl extends AbstractSessionImpl
|
||||||
this.autoCloseSessionEnabled = false;
|
this.autoCloseSessionEnabled = false;
|
||||||
this.connectionReleaseMode = null;
|
this.connectionReleaseMode = null;
|
||||||
|
|
||||||
|
loadQueryInfluencers = new LoadQueryInfluencers( factory );
|
||||||
|
|
||||||
if ( factory.getStatistics().isStatisticsEnabled() ) {
|
if ( factory.getStatistics().isStatisticsEnabled() ) {
|
||||||
factory.getStatisticsImplementor().openSession();
|
factory.getStatisticsImplementor().openSession();
|
||||||
}
|
}
|
||||||
|
@ -239,6 +241,8 @@ public final class SessionImpl extends AbstractSessionImpl
|
||||||
this.connectionReleaseMode = connectionReleaseMode;
|
this.connectionReleaseMode = connectionReleaseMode;
|
||||||
this.jdbcContext = new JDBCContext( this, connection, interceptor );
|
this.jdbcContext = new JDBCContext( this, connection, interceptor );
|
||||||
|
|
||||||
|
loadQueryInfluencers = new LoadQueryInfluencers( factory );
|
||||||
|
|
||||||
if ( factory.getStatistics().isStatisticsEnabled() ) {
|
if ( factory.getStatistics().isStatisticsEnabled() ) {
|
||||||
factory.getStatisticsImplementor().openSession();
|
factory.getStatisticsImplementor().openSession();
|
||||||
}
|
}
|
||||||
|
@ -1048,75 +1052,6 @@ public final class SessionImpl extends AbstractSessionImpl
|
||||||
flush();
|
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
|
* Retrieve a list of persistent objects using a hibernate query
|
||||||
|
@ -1432,7 +1367,7 @@ public final class SessionImpl extends AbstractSessionImpl
|
||||||
return listFilter( collection, filter, new QueryParameters( new Type[]{null, type}, new Object[]{null, value} ) );
|
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 {
|
throws HibernateException {
|
||||||
Object[] vals = new Object[values.length + 1];
|
Object[] vals = new Object[values.length + 1];
|
||||||
Type[] typs = new Type[types.length + 1];
|
Type[] typs = new Type[types.length + 1];
|
||||||
|
@ -1491,7 +1426,7 @@ public final class SessionImpl extends AbstractSessionImpl
|
||||||
return plan;
|
return plan;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List listFilter(Object collection, String filter, QueryParameters queryParameters)
|
public List listFilter(Object collection, String filter, QueryParameters queryParameters)
|
||||||
throws HibernateException {
|
throws HibernateException {
|
||||||
errorIfClosed();
|
errorIfClosed();
|
||||||
checkTransactionSynchStatus();
|
checkTransactionSynchStatus();
|
||||||
|
@ -1511,7 +1446,7 @@ public final class SessionImpl extends AbstractSessionImpl
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator iterateFilter(Object collection, String filter, QueryParameters queryParameters)
|
public Iterator iterateFilter(Object collection, String filter, QueryParameters queryParameters)
|
||||||
throws HibernateException {
|
throws HibernateException {
|
||||||
errorIfClosed();
|
errorIfClosed();
|
||||||
checkTransactionSynchStatus();
|
checkTransactionSynchStatus();
|
||||||
|
@ -1552,7 +1487,7 @@ public final class SessionImpl extends AbstractSessionImpl
|
||||||
factory,
|
factory,
|
||||||
criteria,
|
criteria,
|
||||||
entityName,
|
entityName,
|
||||||
getEnabledFilters()
|
getLoadQueryInfluencers()
|
||||||
);
|
);
|
||||||
autoFlushIfRequired( loader.getQuerySpaces() );
|
autoFlushIfRequired( loader.getQuerySpaces() );
|
||||||
dontFlushFromFind++;
|
dontFlushFromFind++;
|
||||||
|
@ -1579,7 +1514,7 @@ public final class SessionImpl extends AbstractSessionImpl
|
||||||
factory,
|
factory,
|
||||||
criteria,
|
criteria,
|
||||||
implementors[i],
|
implementors[i],
|
||||||
getEnabledFilters()
|
getLoadQueryInfluencers()
|
||||||
);
|
);
|
||||||
|
|
||||||
spaces.addAll( loaders[i].getQuerySpaces() );
|
spaces.addAll( loaders[i].getQuerySpaces() );
|
||||||
|
@ -1680,7 +1615,7 @@ public final class SessionImpl extends AbstractSessionImpl
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScrollableResults scrollCustomQuery(CustomQuery customQuery, QueryParameters queryParameters)
|
public ScrollableResults scrollCustomQuery(CustomQuery customQuery, QueryParameters queryParameters)
|
||||||
throws HibernateException {
|
throws HibernateException {
|
||||||
errorIfClosed();
|
errorIfClosed();
|
||||||
checkTransactionSynchStatus();
|
checkTransactionSynchStatus();
|
||||||
|
@ -1734,7 +1669,7 @@ public final class SessionImpl extends AbstractSessionImpl
|
||||||
return factory;
|
return factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initializeCollection(PersistentCollection collection, boolean writing)
|
public void initializeCollection(PersistentCollection collection, boolean writing)
|
||||||
throws HibernateException {
|
throws HibernateException {
|
||||||
errorIfClosed();
|
errorIfClosed();
|
||||||
checkTransactionSynchStatus();
|
checkTransactionSynchStatus();
|
||||||
|
@ -1882,23 +1817,107 @@ public final class SessionImpl extends AbstractSessionImpl
|
||||||
// nothing to do in a stateful session
|
// nothing to do in a stateful session
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getFetchProfile() {
|
|
||||||
checkTransactionSynchStatus();
|
|
||||||
return fetchProfile;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JDBCContext getJDBCContext() {
|
public JDBCContext getJDBCContext() {
|
||||||
errorIfClosed();
|
errorIfClosed();
|
||||||
checkTransactionSynchStatus();
|
checkTransactionSynchStatus();
|
||||||
return jdbcContext;
|
return jdbcContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 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) {
|
public void setFetchProfile(String fetchProfile) {
|
||||||
errorIfClosed();
|
errorIfClosed();
|
||||||
checkTransactionSynchStatus();
|
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() {
|
private void checkTransactionSynchStatus() {
|
||||||
if ( jdbcContext != null && !isClosed() ) {
|
if ( jdbcContext != null && !isClosed() ) {
|
||||||
jdbcContext.registerSynchronizationIfPossible();
|
jdbcContext.registerSynchronizationIfPossible();
|
||||||
|
@ -1923,7 +1942,6 @@ public final class SessionImpl extends AbstractSessionImpl
|
||||||
cacheMode = CacheMode.parse( ( String ) ois.readObject() );
|
cacheMode = CacheMode.parse( ( String ) ois.readObject() );
|
||||||
flushBeforeCompletionEnabled = ois.readBoolean();
|
flushBeforeCompletionEnabled = ois.readBoolean();
|
||||||
autoCloseSessionEnabled = ois.readBoolean();
|
autoCloseSessionEnabled = ois.readBoolean();
|
||||||
fetchProfile = ( String ) ois.readObject();
|
|
||||||
interceptor = ( Interceptor ) ois.readObject();
|
interceptor = ( Interceptor ) ois.readObject();
|
||||||
|
|
||||||
factory = SessionFactoryImpl.deserialize( ois );
|
factory = SessionFactoryImpl.deserialize( ois );
|
||||||
|
@ -1936,12 +1954,13 @@ public final class SessionImpl extends AbstractSessionImpl
|
||||||
persistenceContext = StatefulPersistenceContext.deserialize( ois, this );
|
persistenceContext = StatefulPersistenceContext.deserialize( ois, this );
|
||||||
actionQueue = ActionQueue.deserialize( ois, this );
|
actionQueue = ActionQueue.deserialize( ois, this );
|
||||||
|
|
||||||
enabledFilters = ( Map ) ois.readObject();
|
loadQueryInfluencers = ( LoadQueryInfluencers ) ois.readObject();
|
||||||
|
|
||||||
childSessionsByEntityMode = ( Map ) ois.readObject();
|
childSessionsByEntityMode = ( Map ) ois.readObject();
|
||||||
|
|
||||||
Iterator iter = enabledFilters.values().iterator();
|
Iterator iter = loadQueryInfluencers.getEnabledFilters().values().iterator();
|
||||||
while ( iter.hasNext() ) {
|
while ( iter.hasNext() ) {
|
||||||
( ( FilterImpl ) iter.next() ).afterDeserialize(factory);
|
( ( FilterImpl ) iter.next() ).afterDeserialize( factory );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( isRootSession && childSessionsByEntityMode != null ) {
|
if ( isRootSession && childSessionsByEntityMode != null ) {
|
||||||
|
@ -1975,7 +1994,6 @@ public final class SessionImpl extends AbstractSessionImpl
|
||||||
oos.writeObject( cacheMode.toString() );
|
oos.writeObject( cacheMode.toString() );
|
||||||
oos.writeBoolean( flushBeforeCompletionEnabled );
|
oos.writeBoolean( flushBeforeCompletionEnabled );
|
||||||
oos.writeBoolean( autoCloseSessionEnabled );
|
oos.writeBoolean( autoCloseSessionEnabled );
|
||||||
oos.writeObject( fetchProfile );
|
|
||||||
// we need to writeObject() on this since interceptor is user defined
|
// we need to writeObject() on this since interceptor is user defined
|
||||||
oos.writeObject( interceptor );
|
oos.writeObject( interceptor );
|
||||||
|
|
||||||
|
@ -1989,7 +2007,7 @@ public final class SessionImpl extends AbstractSessionImpl
|
||||||
actionQueue.serialize( oos );
|
actionQueue.serialize( oos );
|
||||||
|
|
||||||
// todo : look at optimizing these...
|
// todo : look at optimizing these...
|
||||||
oos.writeObject( enabledFilters );
|
oos.writeObject( loadQueryInfluencers );
|
||||||
oos.writeObject( childSessionsByEntityMode );
|
oos.writeObject( childSessionsByEntityMode );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,7 @@ import org.hibernate.engine.PersistenceContext;
|
||||||
import org.hibernate.engine.QueryParameters;
|
import org.hibernate.engine.QueryParameters;
|
||||||
import org.hibernate.engine.StatefulPersistenceContext;
|
import org.hibernate.engine.StatefulPersistenceContext;
|
||||||
import org.hibernate.engine.Versioning;
|
import org.hibernate.engine.Versioning;
|
||||||
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
import org.hibernate.engine.query.HQLQueryPlan;
|
import org.hibernate.engine.query.HQLQueryPlan;
|
||||||
import org.hibernate.engine.query.NativeSQLQueryPlan;
|
import org.hibernate.engine.query.NativeSQLQueryPlan;
|
||||||
import org.hibernate.engine.query.sql.NativeSQLQuerySpecification;
|
import org.hibernate.engine.query.sql.NativeSQLQuerySpecification;
|
||||||
|
@ -527,12 +528,12 @@ public class StatelessSessionImpl extends AbstractSessionImpl
|
||||||
errorIfClosed();
|
errorIfClosed();
|
||||||
String entityName = criteria.getEntityOrClassName();
|
String entityName = criteria.getEntityOrClassName();
|
||||||
CriteriaLoader loader = new CriteriaLoader(
|
CriteriaLoader loader = new CriteriaLoader(
|
||||||
getOuterJoinLoadable(entityName),
|
getOuterJoinLoadable( entityName ),
|
||||||
factory,
|
factory,
|
||||||
criteria,
|
criteria,
|
||||||
entityName,
|
entityName,
|
||||||
getEnabledFilters()
|
getLoadQueryInfluencers()
|
||||||
);
|
);
|
||||||
return loader.scroll(this, scrollMode);
|
return loader.scroll(this, scrollMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -548,7 +549,7 @@ public class StatelessSessionImpl extends AbstractSessionImpl
|
||||||
factory,
|
factory,
|
||||||
criteria,
|
criteria,
|
||||||
implementors[i],
|
implementors[i],
|
||||||
getEnabledFilters()
|
getLoadQueryInfluencers()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -623,6 +624,10 @@ public class StatelessSessionImpl extends AbstractSessionImpl
|
||||||
return jdbcContext;
|
return jdbcContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LoadQueryInfluencers getLoadQueryInfluencers() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public void setFetchProfile(String name) {}
|
public void setFetchProfile(String name) {}
|
||||||
|
|
||||||
public void afterTransactionBegin(Transaction tx) {}
|
public void afterTransactionBegin(Transaction tx) {}
|
||||||
|
|
|
@ -26,13 +26,16 @@ package org.hibernate.loader;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Iterator;
|
||||||
|
|
||||||
import org.hibernate.FetchMode;
|
import org.hibernate.FetchMode;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.engine.CascadeStyle;
|
import org.hibernate.engine.CascadeStyle;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
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.Loadable;
|
||||||
import org.hibernate.persister.entity.OuterJoinLoadable;
|
import org.hibernate.persister.entity.OuterJoinLoadable;
|
||||||
import org.hibernate.sql.JoinFragment;
|
import org.hibernate.sql.JoinFragment;
|
||||||
|
@ -51,55 +54,60 @@ public abstract class AbstractEntityJoinWalker extends JoinWalker {
|
||||||
private final OuterJoinLoadable persister;
|
private final OuterJoinLoadable persister;
|
||||||
private final String alias;
|
private final String alias;
|
||||||
|
|
||||||
public AbstractEntityJoinWalker(OuterJoinLoadable persister, SessionFactoryImplementor factory, Map enabledFilters) {
|
public AbstractEntityJoinWalker(
|
||||||
this( persister, factory, enabledFilters, null );
|
OuterJoinLoadable persister,
|
||||||
|
SessionFactoryImplementor factory,
|
||||||
|
LoadQueryInfluencers loadQueryInfluencers) {
|
||||||
|
this( persister, factory, loadQueryInfluencers, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbstractEntityJoinWalker(OuterJoinLoadable persister, SessionFactoryImplementor factory, Map enabledFilters, String alias) {
|
public AbstractEntityJoinWalker(
|
||||||
super( factory, enabledFilters );
|
OuterJoinLoadable persister,
|
||||||
|
SessionFactoryImplementor factory,
|
||||||
|
LoadQueryInfluencers loadQueryInfluencers,
|
||||||
|
String alias) {
|
||||||
|
super( factory, loadQueryInfluencers );
|
||||||
this.persister = persister;
|
this.persister = persister;
|
||||||
this.alias = ( alias == null ) ? generateRootAlias( persister.getEntityName() ) : alias;
|
this.alias = ( alias == null ) ? generateRootAlias( persister.getEntityName() ) : alias;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final void initAll(
|
protected final void initAll(
|
||||||
final String whereString,
|
final String whereString,
|
||||||
final String orderByString,
|
final String orderByString,
|
||||||
final LockMode lockMode)
|
final LockMode lockMode) throws MappingException {
|
||||||
throws MappingException {
|
|
||||||
walkEntityTree( persister, getAlias() );
|
walkEntityTree( persister, getAlias() );
|
||||||
List allAssociations = new ArrayList();
|
List allAssociations = new ArrayList();
|
||||||
allAssociations.addAll(associations);
|
allAssociations.addAll(associations);
|
||||||
allAssociations.add( new OuterJoinableAssociation(
|
allAssociations.add(
|
||||||
persister.getEntityType(),
|
new OuterJoinableAssociation(
|
||||||
null,
|
persister.getEntityType(),
|
||||||
null,
|
null,
|
||||||
alias,
|
null,
|
||||||
JoinFragment.LEFT_OUTER_JOIN,
|
alias,
|
||||||
getFactory(),
|
JoinFragment.LEFT_OUTER_JOIN,
|
||||||
CollectionHelper.EMPTY_MAP
|
getFactory(),
|
||||||
) );
|
CollectionHelper.EMPTY_MAP
|
||||||
|
)
|
||||||
|
);
|
||||||
initPersisters(allAssociations, lockMode);
|
initPersisters(allAssociations, lockMode);
|
||||||
initStatementString( whereString, orderByString, lockMode);
|
initStatementString( whereString, orderByString, lockMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final void initProjection(
|
protected final void initProjection(
|
||||||
final String projectionString,
|
final String projectionString,
|
||||||
final String whereString,
|
final String whereString,
|
||||||
final String orderByString,
|
final String orderByString,
|
||||||
final String groupByString,
|
final String groupByString,
|
||||||
final LockMode lockMode)
|
final LockMode lockMode) throws MappingException {
|
||||||
throws MappingException {
|
|
||||||
walkEntityTree( persister, getAlias() );
|
walkEntityTree( persister, getAlias() );
|
||||||
persisters = new Loadable[0];
|
persisters = new Loadable[0];
|
||||||
initStatementString(projectionString, whereString, orderByString, groupByString, lockMode);
|
initStatementString(projectionString, whereString, orderByString, groupByString, lockMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initStatementString(
|
private void initStatementString(
|
||||||
final String condition,
|
final String condition,
|
||||||
final String orderBy,
|
final String orderBy,
|
||||||
final LockMode lockMode)
|
final LockMode lockMode) throws MappingException {
|
||||||
throws MappingException {
|
|
||||||
initStatementString(null, condition, orderBy, "", lockMode);
|
initStatementString(null, condition, orderBy, "", lockMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +157,33 @@ public abstract class AbstractEntityJoinWalker extends JoinWalker {
|
||||||
* The superclass deliberately excludes collections
|
* The superclass deliberately excludes collections
|
||||||
*/
|
*/
|
||||||
protected boolean isJoinedFetchEnabled(AssociationType type, FetchMode config, CascadeStyle cascadeStyle) {
|
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();
|
public abstract String getComment();
|
||||||
|
|
|
@ -29,7 +29,6 @@ import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.hibernate.FetchMode;
|
import org.hibernate.FetchMode;
|
||||||
|
@ -39,6 +38,9 @@ import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.engine.CascadeStyle;
|
import org.hibernate.engine.CascadeStyle;
|
||||||
import org.hibernate.engine.JoinHelper;
|
import org.hibernate.engine.JoinHelper;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
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.CollectionPersister;
|
||||||
import org.hibernate.persister.collection.QueryableCollection;
|
import org.hibernate.persister.collection.QueryableCollection;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
@ -69,7 +71,7 @@ public class JoinWalker {
|
||||||
private final SessionFactoryImplementor factory;
|
private final SessionFactoryImplementor factory;
|
||||||
protected final List associations = new ArrayList();
|
protected final List associations = new ArrayList();
|
||||||
private final Set visitedAssociationKeys = new HashSet();
|
private final Set visitedAssociationKeys = new HashSet();
|
||||||
private final Map enabledFilters;
|
private final LoadQueryInfluencers loadQueryInfluencers;
|
||||||
|
|
||||||
protected String[] suffixes;
|
protected String[] suffixes;
|
||||||
protected String[] collectionSuffixes;
|
protected String[] collectionSuffixes;
|
||||||
|
@ -81,6 +83,14 @@ public class JoinWalker {
|
||||||
protected String[] aliases;
|
protected String[] aliases;
|
||||||
protected LockMode[] lockModeArray;
|
protected LockMode[] lockModeArray;
|
||||||
protected String sql;
|
protected String sql;
|
||||||
|
|
||||||
|
protected JoinWalker(
|
||||||
|
SessionFactoryImplementor factory,
|
||||||
|
LoadQueryInfluencers loadQueryInfluencers) {
|
||||||
|
this.factory = factory;
|
||||||
|
this.loadQueryInfluencers = loadQueryInfluencers;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public String[] getCollectionSuffixes() {
|
public String[] getCollectionSuffixes() {
|
||||||
return collectionSuffixes;
|
return collectionSuffixes;
|
||||||
|
@ -169,14 +179,9 @@ public class JoinWalker {
|
||||||
protected Dialect getDialect() {
|
protected Dialect getDialect() {
|
||||||
return factory.getDialect();
|
return factory.getDialect();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Map getEnabledFilters() {
|
|
||||||
return enabledFilters;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected JoinWalker(SessionFactoryImplementor factory, Map enabledFilters) {
|
public LoadQueryInfluencers getLoadQueryInfluencers() {
|
||||||
this.factory = factory;
|
return loadQueryInfluencers;
|
||||||
this.enabledFilters = enabledFilters;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -184,15 +189,13 @@ public class JoinWalker {
|
||||||
* of associations to be fetched by outerjoin (if necessary)
|
* of associations to be fetched by outerjoin (if necessary)
|
||||||
*/
|
*/
|
||||||
private void addAssociationToJoinTreeIfNecessary(
|
private void addAssociationToJoinTreeIfNecessary(
|
||||||
final AssociationType type,
|
final AssociationType type,
|
||||||
final String[] aliasedLhsColumns,
|
final String[] aliasedLhsColumns,
|
||||||
final String alias,
|
final String alias,
|
||||||
final String path,
|
final String path,
|
||||||
int currentDepth,
|
int currentDepth,
|
||||||
final int joinType)
|
final int joinType) throws MappingException {
|
||||||
throws MappingException {
|
if ( joinType >= 0 ) {
|
||||||
|
|
||||||
if (joinType>=0) {
|
|
||||||
addAssociationToJoinTree(
|
addAssociationToJoinTree(
|
||||||
type,
|
type,
|
||||||
aliasedLhsColumns,
|
aliasedLhsColumns,
|
||||||
|
@ -200,9 +203,8 @@ public class JoinWalker {
|
||||||
path,
|
path,
|
||||||
currentDepth,
|
currentDepth,
|
||||||
joinType
|
joinType
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -210,35 +212,37 @@ public class JoinWalker {
|
||||||
* of associations to be fetched by outerjoin
|
* of associations to be fetched by outerjoin
|
||||||
*/
|
*/
|
||||||
private void addAssociationToJoinTree(
|
private void addAssociationToJoinTree(
|
||||||
final AssociationType type,
|
final AssociationType type,
|
||||||
final String[] aliasedLhsColumns,
|
final String[] aliasedLhsColumns,
|
||||||
final String alias,
|
final String alias,
|
||||||
final String path,
|
String path,
|
||||||
final int currentDepth,
|
final int currentDepth,
|
||||||
final int joinType)
|
final int joinType) throws MappingException {
|
||||||
throws MappingException {
|
|
||||||
|
|
||||||
Joinable joinable = type.getAssociatedJoinable( getFactory() );
|
Joinable joinable = type.getAssociatedJoinable( getFactory() );
|
||||||
|
|
||||||
String subalias = generateTableAlias(
|
// important to generate alias based on size of association collection
|
||||||
associations.size()+1, //before adding to collection!
|
// *before* adding this join to that collection
|
||||||
path,
|
String subalias = generateTableAlias( associations.size() + 1, path, joinable );
|
||||||
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(
|
OuterJoinableAssociation assoc = new OuterJoinableAssociation(
|
||||||
type,
|
type,
|
||||||
alias,
|
alias,
|
||||||
aliasedLhsColumns,
|
aliasedLhsColumns,
|
||||||
subalias,
|
subalias,
|
||||||
joinType,
|
joinType,
|
||||||
getFactory(),
|
getFactory(),
|
||||||
enabledFilters
|
loadQueryInfluencers.getEnabledFilters()
|
||||||
);
|
);
|
||||||
assoc.validateJoin(path);
|
assoc.validateJoin( path );
|
||||||
associations.add(assoc);
|
associations.add( assoc );
|
||||||
|
|
||||||
int nextDepth = currentDepth+1;
|
int nextDepth = currentDepth + 1;
|
||||||
|
// path = "";
|
||||||
if ( !joinable.isCollection() ) {
|
if ( !joinable.isCollection() ) {
|
||||||
if (joinable instanceof OuterJoinLoadable) {
|
if (joinable instanceof OuterJoinLoadable) {
|
||||||
walkEntityTree(
|
walkEntityTree(
|
||||||
|
@ -263,11 +267,19 @@ public class JoinWalker {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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)
|
protected final void walkEntityTree(
|
||||||
throws MappingException {
|
OuterJoinLoadable persister,
|
||||||
walkEntityTree(persister, alias, "", 0);
|
String alias) throws MappingException {
|
||||||
|
walkEntityTree( persister, alias, "", 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -344,38 +356,49 @@ public class JoinWalker {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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(
|
private void walkEntityAssociationTree(
|
||||||
final AssociationType associationType,
|
final AssociationType associationType,
|
||||||
final OuterJoinLoadable persister,
|
final OuterJoinLoadable persister,
|
||||||
final int propertyNumber,
|
final int propertyNumber,
|
||||||
final String alias,
|
final String alias,
|
||||||
final String path,
|
final String path,
|
||||||
final boolean nullable,
|
final boolean nullable,
|
||||||
final int currentDepth)
|
final int currentDepth) throws MappingException {
|
||||||
throws MappingException {
|
|
||||||
|
|
||||||
String[] aliasedLhsColumns = JoinHelper.getAliasedLHSColumnNames(
|
String[] aliasedLhsColumns = JoinHelper.getAliasedLHSColumnNames(
|
||||||
associationType, alias, propertyNumber, persister, getFactory()
|
associationType, alias, propertyNumber, persister, getFactory()
|
||||||
);
|
);
|
||||||
|
|
||||||
String[] lhsColumns = JoinHelper.getLHSColumnNames(
|
String[] lhsColumns = JoinHelper.getLHSColumnNames(
|
||||||
associationType, propertyNumber, persister, getFactory()
|
associationType, propertyNumber, persister, getFactory()
|
||||||
);
|
);
|
||||||
String lhsTable = JoinHelper.getLHSTableName(associationType, propertyNumber, persister);
|
String lhsTable = JoinHelper.getLHSTableName(associationType, propertyNumber, persister);
|
||||||
|
|
||||||
String subpath = subPath( path, persister.getSubclassPropertyName(propertyNumber) );
|
String subpath = subPath( path, persister.getSubclassPropertyName(propertyNumber) );
|
||||||
int joinType = getJoinType(
|
int joinType = getJoinType(
|
||||||
associationType,
|
persister,
|
||||||
persister.getFetchMode(propertyNumber),
|
|
||||||
subpath,
|
subpath,
|
||||||
|
propertyNumber,
|
||||||
|
associationType,
|
||||||
|
persister.getFetchMode( propertyNumber ),
|
||||||
|
persister.getCascadeStyle( propertyNumber ),
|
||||||
lhsTable,
|
lhsTable,
|
||||||
lhsColumns,
|
lhsColumns,
|
||||||
nullable,
|
nullable,
|
||||||
currentDepth,
|
currentDepth
|
||||||
persister.getCascadeStyle(propertyNumber)
|
);
|
||||||
);
|
|
||||||
addAssociationToJoinTreeIfNecessary(
|
addAssociationToJoinTreeIfNecessary(
|
||||||
associationType,
|
associationType,
|
||||||
aliasedLhsColumns,
|
aliasedLhsColumns,
|
||||||
|
@ -383,27 +406,110 @@ public class JoinWalker {
|
||||||
subpath,
|
subpath,
|
||||||
currentDepth,
|
currentDepth,
|
||||||
joinType
|
joinType
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For an entity class, add to a list of associations to be fetched
|
* Determine the appropriate type of join (if any) to use to fetch the
|
||||||
* by outerjoin
|
* 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 ??
|
||||||
*/
|
*/
|
||||||
private final void walkEntityTree(
|
protected int getJoinType(
|
||||||
final OuterJoinLoadable persister,
|
OuterJoinLoadable persister,
|
||||||
final String alias,
|
final String path,
|
||||||
final String path,
|
int propertyNumber,
|
||||||
final int currentDepth)
|
AssociationType associationType,
|
||||||
throws MappingException {
|
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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 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();
|
int n = persister.countSubclassProperties();
|
||||||
for ( int i=0; i<n; i++ ) {
|
for ( int i = 0; i < n; i++ ) {
|
||||||
Type type = persister.getSubclassPropertyType(i);
|
Type type = persister.getSubclassPropertyType(i);
|
||||||
if ( type.isAssociationType() ) {
|
if ( type.isAssociationType() ) {
|
||||||
walkEntityAssociationTree(
|
walkEntityAssociationTree(
|
||||||
(AssociationType) type,
|
( AssociationType ) type,
|
||||||
persister,
|
persister,
|
||||||
i,
|
i,
|
||||||
alias,
|
alias,
|
||||||
|
@ -414,7 +520,7 @@ public class JoinWalker {
|
||||||
}
|
}
|
||||||
else if ( type.isComponentType() ) {
|
else if ( type.isComponentType() ) {
|
||||||
walkComponentTree(
|
walkComponentTree(
|
||||||
(AbstractComponentType) type,
|
( AbstractComponentType ) type,
|
||||||
i,
|
i,
|
||||||
0,
|
0,
|
||||||
persister,
|
persister,
|
||||||
|
@ -428,28 +534,34 @@ public class JoinWalker {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For a component, add to a list of associations to be fetched by outerjoin
|
* 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(
|
private void walkComponentTree(
|
||||||
final AbstractComponentType componentType,
|
final AbstractComponentType componentType,
|
||||||
final int propertyNumber,
|
final int propertyNumber,
|
||||||
int begin,
|
int begin,
|
||||||
final OuterJoinLoadable persister,
|
final OuterJoinLoadable persister,
|
||||||
final String alias,
|
final String alias,
|
||||||
final String path,
|
final String path,
|
||||||
final int currentDepth
|
final int currentDepth) throws MappingException {
|
||||||
) throws MappingException {
|
|
||||||
|
|
||||||
Type[] types = componentType.getSubtypes();
|
Type[] types = componentType.getSubtypes();
|
||||||
String[] propertyNames = componentType.getPropertyNames();
|
String[] propertyNames = componentType.getPropertyNames();
|
||||||
for ( int i=0; i <types.length; i++ ) {
|
for ( int i = 0; i < types.length; i++ ) {
|
||||||
|
|
||||||
if ( types[i].isAssociationType() ) {
|
if ( types[i].isAssociationType() ) {
|
||||||
AssociationType associationType = (AssociationType) types[i];
|
AssociationType associationType = (AssociationType) types[i];
|
||||||
|
|
||||||
String[] aliasedLhsColumns = JoinHelper.getAliasedLHSColumnNames(
|
String[] aliasedLhsColumns = JoinHelper.getAliasedLHSColumnNames(
|
||||||
associationType, alias, propertyNumber, begin, persister, getFactory()
|
associationType, alias, propertyNumber, begin, persister, getFactory()
|
||||||
);
|
);
|
||||||
|
|
||||||
String[] lhsColumns = JoinHelper.getLHSColumnNames(
|
String[] lhsColumns = JoinHelper.getLHSColumnNames(
|
||||||
associationType, propertyNumber, begin, persister, getFactory()
|
associationType, propertyNumber, begin, persister, getFactory()
|
||||||
);
|
);
|
||||||
|
@ -458,15 +570,17 @@ public class JoinWalker {
|
||||||
String subpath = subPath( path, propertyNames[i] );
|
String subpath = subPath( path, propertyNames[i] );
|
||||||
final boolean[] propertyNullability = componentType.getPropertyNullability();
|
final boolean[] propertyNullability = componentType.getPropertyNullability();
|
||||||
final int joinType = getJoinType(
|
final int joinType = getJoinType(
|
||||||
|
persister,
|
||||||
|
subpath,
|
||||||
|
propertyNumber,
|
||||||
associationType,
|
associationType,
|
||||||
componentType.getFetchMode(i),
|
componentType.getFetchMode(i),
|
||||||
subpath,
|
componentType.getCascadeStyle(i),
|
||||||
lhsTable,
|
lhsTable,
|
||||||
lhsColumns,
|
lhsColumns,
|
||||||
propertyNullability==null || propertyNullability[i],
|
propertyNullability==null || propertyNullability[i],
|
||||||
currentDepth,
|
currentDepth
|
||||||
componentType.getCascadeStyle(i)
|
);
|
||||||
);
|
|
||||||
addAssociationToJoinTreeIfNecessary(
|
addAssociationToJoinTreeIfNecessary(
|
||||||
associationType,
|
associationType,
|
||||||
aliasedLhsColumns,
|
aliasedLhsColumns,
|
||||||
|
@ -474,23 +588,22 @@ public class JoinWalker {
|
||||||
subpath,
|
subpath,
|
||||||
currentDepth,
|
currentDepth,
|
||||||
joinType
|
joinType
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
else if ( types[i].isComponentType() ) {
|
else if ( types[i].isComponentType() ) {
|
||||||
String subpath = subPath( path, propertyNames[i] );
|
String subpath = subPath( path, propertyNames[i] );
|
||||||
walkComponentTree(
|
walkComponentTree(
|
||||||
(AbstractComponentType) types[i],
|
( AbstractComponentType ) types[i],
|
||||||
propertyNumber,
|
propertyNumber,
|
||||||
begin,
|
begin,
|
||||||
persister,
|
persister,
|
||||||
alias,
|
alias,
|
||||||
subpath,
|
subpath,
|
||||||
currentDepth
|
currentDepth
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
begin += types[i].getColumnSpan( getFactory() );
|
||||||
begin+=types[i].getColumnSpan( getFactory() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -499,13 +612,12 @@ public class JoinWalker {
|
||||||
* For a composite element, add to a list of associations to be fetched by outerjoin
|
* For a composite element, add to a list of associations to be fetched by outerjoin
|
||||||
*/
|
*/
|
||||||
private void walkCompositeElementTree(
|
private void walkCompositeElementTree(
|
||||||
final AbstractComponentType compositeType,
|
final AbstractComponentType compositeType,
|
||||||
final String[] cols,
|
final String[] cols,
|
||||||
final QueryableCollection persister,
|
final QueryableCollection persister,
|
||||||
final String alias,
|
final String alias,
|
||||||
final String path,
|
final String path,
|
||||||
final int currentDepth)
|
final int currentDepth) throws MappingException {
|
||||||
throws MappingException {
|
|
||||||
|
|
||||||
Type[] types = compositeType.getSubtypes();
|
Type[] types = compositeType.getSubtypes();
|
||||||
String[] propertyNames = compositeType.getPropertyNames();
|
String[] propertyNames = compositeType.getPropertyNames();
|
||||||
|
@ -570,33 +682,6 @@ public class JoinWalker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
* Use an inner join if it is a non-null association and this
|
||||||
* is the "first" join in a series
|
* is the "first" join in a series
|
||||||
|
@ -604,9 +689,9 @@ public class JoinWalker {
|
||||||
protected int getJoinType(boolean nullable, int currentDepth) {
|
protected int getJoinType(boolean nullable, int currentDepth) {
|
||||||
//TODO: this is too conservative; if all preceding joins were
|
//TODO: this is too conservative; if all preceding joins were
|
||||||
// also inner joins, we could use an inner join here
|
// also inner joins, we could use an inner join here
|
||||||
return !nullable && currentDepth==0 ?
|
return !nullable && currentDepth == 0
|
||||||
JoinFragment.INNER_JOIN :
|
? JoinFragment.INNER_JOIN
|
||||||
JoinFragment.LEFT_OUTER_JOIN;
|
: JoinFragment.LEFT_OUTER_JOIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isTooDeep(int currentDepth) {
|
protected boolean isTooDeep(int currentDepth) {
|
||||||
|
@ -654,8 +739,7 @@ public class JoinWalker {
|
||||||
protected String generateTableAlias(
|
protected String generateTableAlias(
|
||||||
final int n,
|
final int n,
|
||||||
final String path,
|
final String path,
|
||||||
final Joinable joinable
|
final Joinable joinable) {
|
||||||
) {
|
|
||||||
return StringHelper.generateAlias( joinable.getName(), n );
|
return StringHelper.generateAlias( joinable.getName(), n );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,10 +25,12 @@
|
||||||
package org.hibernate.loader;
|
package org.hibernate.loader;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
import org.hibernate.persister.collection.CollectionPersister;
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
import org.hibernate.persister.entity.Loadable;
|
import org.hibernate.persister.entity.Loadable;
|
||||||
import org.hibernate.type.EntityType;
|
import org.hibernate.type.EntityType;
|
||||||
|
@ -54,15 +56,17 @@ public abstract class OuterJoinLoader extends BasicLoader {
|
||||||
protected String[] suffixes;
|
protected String[] suffixes;
|
||||||
protected String[] collectionSuffixes;
|
protected String[] collectionSuffixes;
|
||||||
|
|
||||||
private Map enabledFilters;
|
private LoadQueryInfluencers loadQueryInfluencers;
|
||||||
|
|
||||||
protected final Dialect getDialect() {
|
protected final Dialect getDialect() {
|
||||||
return getFactory().getDialect();
|
return getFactory().getDialect();
|
||||||
}
|
}
|
||||||
|
|
||||||
public OuterJoinLoader(SessionFactoryImplementor factory, Map enabledFilters) {
|
public OuterJoinLoader(
|
||||||
super(factory);
|
SessionFactoryImplementor factory,
|
||||||
this.enabledFilters = enabledFilters;
|
LoadQueryInfluencers loadQueryInfluencers) {
|
||||||
|
super( factory );
|
||||||
|
this.loadQueryInfluencers = loadQueryInfluencers;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String[] getSuffixes() {
|
protected String[] getSuffixes() {
|
||||||
|
@ -92,9 +96,9 @@ public abstract class OuterJoinLoader extends BasicLoader {
|
||||||
protected LockMode[] getLockModes(Map lockModes) {
|
protected LockMode[] getLockModes(Map lockModes) {
|
||||||
return lockModeArray;
|
return lockModeArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map getEnabledFilters() {
|
public LoadQueryInfluencers getLoadQueryInfluencers() {
|
||||||
return enabledFilters;
|
return loadQueryInfluencers;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final String[] getAliases() {
|
protected final String[] getAliases() {
|
||||||
|
|
|
@ -36,6 +36,12 @@ import org.hibernate.sql.JoinFragment;
|
||||||
import org.hibernate.type.AssociationType;
|
import org.hibernate.type.AssociationType;
|
||||||
import org.hibernate.type.EntityType;
|
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 {
|
public final class OuterJoinableAssociation {
|
||||||
private final AssociationType joinableType;
|
private final AssociationType joinableType;
|
||||||
private final Joinable joinable;
|
private final Joinable joinable;
|
||||||
|
@ -48,14 +54,13 @@ public final class OuterJoinableAssociation {
|
||||||
private final Map enabledFilters;
|
private final Map enabledFilters;
|
||||||
|
|
||||||
public OuterJoinableAssociation(
|
public OuterJoinableAssociation(
|
||||||
AssociationType joinableType,
|
AssociationType joinableType,
|
||||||
String lhsAlias,
|
String lhsAlias,
|
||||||
String[] lhsColumns,
|
String[] lhsColumns,
|
||||||
String rhsAlias,
|
String rhsAlias,
|
||||||
int joinType,
|
int joinType,
|
||||||
SessionFactoryImplementor factory,
|
SessionFactoryImplementor factory,
|
||||||
Map enabledFilters)
|
Map enabledFilters) throws MappingException {
|
||||||
throws MappingException {
|
|
||||||
this.joinableType = joinableType;
|
this.joinableType = joinableType;
|
||||||
this.lhsAlias = lhsAlias;
|
this.lhsAlias = lhsAlias;
|
||||||
this.lhsColumns = lhsColumns;
|
this.lhsColumns = lhsColumns;
|
||||||
|
|
|
@ -34,9 +34,12 @@ import org.hibernate.FetchMode;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
|
import org.hibernate.engine.CascadeStyle;
|
||||||
import org.hibernate.loader.BasicLoader;
|
import org.hibernate.loader.BasicLoader;
|
||||||
import org.hibernate.loader.OuterJoinableAssociation;
|
import org.hibernate.loader.OuterJoinableAssociation;
|
||||||
import org.hibernate.persister.collection.QueryableCollection;
|
import org.hibernate.persister.collection.QueryableCollection;
|
||||||
|
import org.hibernate.persister.entity.OuterJoinLoadable;
|
||||||
import org.hibernate.sql.JoinFragment;
|
import org.hibernate.sql.JoinFragment;
|
||||||
import org.hibernate.sql.Select;
|
import org.hibernate.sql.Select;
|
||||||
import org.hibernate.type.AssociationType;
|
import org.hibernate.type.AssociationType;
|
||||||
|
@ -58,10 +61,9 @@ public class BasicCollectionJoinWalker extends CollectionJoinWalker {
|
||||||
int batchSize,
|
int batchSize,
|
||||||
String subquery,
|
String subquery,
|
||||||
SessionFactoryImplementor factory,
|
SessionFactoryImplementor factory,
|
||||||
Map enabledFilters)
|
LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
|
||||||
throws MappingException {
|
|
||||||
|
|
||||||
super(factory, enabledFilters);
|
super( factory, loadQueryInfluencers );
|
||||||
|
|
||||||
this.collectionPersister = collectionPersister;
|
this.collectionPersister = collectionPersister;
|
||||||
|
|
||||||
|
@ -71,26 +73,25 @@ public class BasicCollectionJoinWalker extends CollectionJoinWalker {
|
||||||
|
|
||||||
List allAssociations = new ArrayList();
|
List allAssociations = new ArrayList();
|
||||||
allAssociations.addAll(associations);
|
allAssociations.addAll(associations);
|
||||||
allAssociations.add( new OuterJoinableAssociation(
|
allAssociations.add(
|
||||||
collectionPersister.getCollectionType(),
|
new OuterJoinableAssociation(
|
||||||
null,
|
collectionPersister.getCollectionType(),
|
||||||
null,
|
null,
|
||||||
alias,
|
null,
|
||||||
JoinFragment.LEFT_OUTER_JOIN,
|
alias,
|
||||||
getFactory(),
|
JoinFragment.LEFT_OUTER_JOIN,
|
||||||
CollectionHelper.EMPTY_MAP
|
getFactory(),
|
||||||
) );
|
CollectionHelper.EMPTY_MAP
|
||||||
|
)
|
||||||
|
);
|
||||||
initPersisters(allAssociations, LockMode.NONE);
|
initPersisters(allAssociations, LockMode.NONE);
|
||||||
initStatementString(alias, batchSize, subquery);
|
initStatementString(alias, batchSize, subquery);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initStatementString(
|
private void initStatementString(
|
||||||
final String alias,
|
final String alias,
|
||||||
final int batchSize,
|
final int batchSize,
|
||||||
final String subquery)
|
final String subquery) throws MappingException {
|
||||||
throws MappingException {
|
|
||||||
|
|
||||||
final int joins = countEntityPersisters( associations );
|
final int joins = countEntityPersisters( associations );
|
||||||
final int collectionJoins = countCollectionPersisters( associations ) + 1;
|
final int collectionJoins = countCollectionPersisters( associations ) + 1;
|
||||||
|
@ -106,7 +107,7 @@ public class BasicCollectionJoinWalker extends CollectionJoinWalker {
|
||||||
);
|
);
|
||||||
|
|
||||||
String manyToManyOrderBy = "";
|
String manyToManyOrderBy = "";
|
||||||
String filter = collectionPersister.filterFragment( alias, getEnabledFilters() );
|
String filter = collectionPersister.filterFragment( alias, getLoadQueryInfluencers().getEnabledFilters() );
|
||||||
if ( collectionPersister.isManyToMany() ) {
|
if ( collectionPersister.isManyToMany() ) {
|
||||||
// from the collection of associations, locate OJA for the
|
// from the collection of associations, locate OJA for the
|
||||||
// ManyToOne corresponding to this persister to fully
|
// ManyToOne corresponding to this persister to fully
|
||||||
|
@ -121,9 +122,9 @@ public class BasicCollectionJoinWalker extends CollectionJoinWalker {
|
||||||
// we found it
|
// we found it
|
||||||
filter += collectionPersister.getManyToManyFilterFragment(
|
filter += collectionPersister.getManyToManyFilterFragment(
|
||||||
oja.getRHSAlias(),
|
oja.getRHSAlias(),
|
||||||
getEnabledFilters()
|
getLoadQueryInfluencers().getEnabledFilters()
|
||||||
);
|
);
|
||||||
manyToManyOrderBy += collectionPersister.getManyToManyOrderByString( oja.getRHSAlias() );
|
manyToManyOrderBy += collectionPersister.getManyToManyOrderByString( oja.getRHSAlias() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,37 +152,36 @@ public class BasicCollectionJoinWalker extends CollectionJoinWalker {
|
||||||
sql = select.toStatementString();
|
sql = select.toStatementString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* We can use an inner join for first many-to-many association
|
|
||||||
*/
|
|
||||||
protected int getJoinType(
|
protected int getJoinType(
|
||||||
AssociationType type,
|
OuterJoinLoadable persister,
|
||||||
FetchMode config,
|
String path,
|
||||||
String path,
|
int propertyNumber,
|
||||||
Set visitedAssociations,
|
AssociationType associationType,
|
||||||
|
FetchMode metadataFetchMode,
|
||||||
|
CascadeStyle metadataCascadeStyle,
|
||||||
String lhsTable,
|
String lhsTable,
|
||||||
String[] lhsColumns,
|
String[] lhsColumns,
|
||||||
boolean nullable,
|
boolean nullable,
|
||||||
int currentDepth)
|
int currentDepth) throws MappingException {
|
||||||
throws MappingException {
|
|
||||||
|
|
||||||
int joinType = super.getJoinType(
|
int joinType = super.getJoinType(
|
||||||
type,
|
persister,
|
||||||
config,
|
path,
|
||||||
path,
|
propertyNumber,
|
||||||
lhsTable,
|
associationType,
|
||||||
lhsColumns,
|
metadataFetchMode,
|
||||||
nullable,
|
metadataCascadeStyle,
|
||||||
currentDepth,
|
lhsTable,
|
||||||
null
|
lhsColumns,
|
||||||
);
|
nullable,
|
||||||
|
currentDepth
|
||||||
|
);
|
||||||
//we can use an inner join for the many-to-many
|
//we can use an inner join for the many-to-many
|
||||||
if ( joinType==JoinFragment.LEFT_OUTER_JOIN && "".equals(path) ) {
|
if ( joinType==JoinFragment.LEFT_OUTER_JOIN && "".equals(path) ) {
|
||||||
joinType=JoinFragment.INNER_JOIN;
|
joinType=JoinFragment.INNER_JOIN;
|
||||||
}
|
}
|
||||||
return joinType;
|
return joinType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getClass().getName() + '(' + collectionPersister.getRole() + ')';
|
return getClass().getName() + '(' + collectionPersister.getRole() + ')';
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,12 +24,11 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.loader.collection;
|
package org.hibernate.loader.collection;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
import org.hibernate.loader.JoinWalker;
|
import org.hibernate.loader.JoinWalker;
|
||||||
import org.hibernate.persister.collection.QueryableCollection;
|
import org.hibernate.persister.collection.QueryableCollection;
|
||||||
|
|
||||||
|
@ -49,18 +48,16 @@ public class BasicCollectionLoader extends CollectionLoader {
|
||||||
public BasicCollectionLoader(
|
public BasicCollectionLoader(
|
||||||
QueryableCollection collectionPersister,
|
QueryableCollection collectionPersister,
|
||||||
SessionFactoryImplementor session,
|
SessionFactoryImplementor session,
|
||||||
Map enabledFilters)
|
LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
|
||||||
throws MappingException {
|
this( collectionPersister, 1, session, loadQueryInfluencers );
|
||||||
this(collectionPersister, 1, session, enabledFilters);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public BasicCollectionLoader(
|
public BasicCollectionLoader(
|
||||||
QueryableCollection collectionPersister,
|
QueryableCollection collectionPersister,
|
||||||
int batchSize,
|
int batchSize,
|
||||||
SessionFactoryImplementor factory,
|
SessionFactoryImplementor factory,
|
||||||
Map enabledFilters)
|
LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
|
||||||
throws MappingException {
|
this( collectionPersister, batchSize, null, factory, loadQueryInfluencers );
|
||||||
this(collectionPersister, batchSize, null, factory, enabledFilters);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected BasicCollectionLoader(
|
protected BasicCollectionLoader(
|
||||||
|
@ -68,18 +65,16 @@ public class BasicCollectionLoader extends CollectionLoader {
|
||||||
int batchSize,
|
int batchSize,
|
||||||
String subquery,
|
String subquery,
|
||||||
SessionFactoryImplementor factory,
|
SessionFactoryImplementor factory,
|
||||||
Map enabledFilters)
|
LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
|
||||||
throws MappingException {
|
super( collectionPersister, factory, loadQueryInfluencers );
|
||||||
|
|
||||||
super(collectionPersister, factory, enabledFilters);
|
|
||||||
|
|
||||||
JoinWalker walker = new BasicCollectionJoinWalker(
|
JoinWalker walker = new BasicCollectionJoinWalker(
|
||||||
collectionPersister,
|
collectionPersister,
|
||||||
batchSize,
|
batchSize,
|
||||||
subquery,
|
subquery,
|
||||||
factory,
|
factory,
|
||||||
enabledFilters
|
loadQueryInfluencers
|
||||||
);
|
);
|
||||||
initFromWalker( walker );
|
initFromWalker( walker );
|
||||||
|
|
||||||
postInstantiate();
|
postInstantiate();
|
||||||
|
|
|
@ -31,6 +31,7 @@ import org.hibernate.HibernateException;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.SessionImplementor;
|
import org.hibernate.engine.SessionImplementor;
|
||||||
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
import org.hibernate.loader.Loader;
|
import org.hibernate.loader.Loader;
|
||||||
import org.hibernate.persister.collection.CollectionPersister;
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
import org.hibernate.persister.collection.QueryableCollection;
|
import org.hibernate.persister.collection.QueryableCollection;
|
||||||
|
@ -77,42 +78,38 @@ public class BatchingCollectionInitializer implements CollectionInitializer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CollectionInitializer createBatchingOneToManyInitializer(
|
public static CollectionInitializer createBatchingOneToManyInitializer(
|
||||||
final QueryableCollection persister,
|
final QueryableCollection persister,
|
||||||
final int maxBatchSize,
|
final int maxBatchSize,
|
||||||
final SessionFactoryImplementor factory,
|
final SessionFactoryImplementor factory,
|
||||||
final Map enabledFilters)
|
final LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
|
||||||
throws MappingException {
|
if ( maxBatchSize > 1 ) {
|
||||||
|
|
||||||
if ( maxBatchSize>1 ) {
|
|
||||||
int[] batchSizesToCreate = ArrayHelper.getBatchSizes(maxBatchSize);
|
int[] batchSizesToCreate = ArrayHelper.getBatchSizes(maxBatchSize);
|
||||||
Loader[] loadersToCreate = new Loader[ batchSizesToCreate.length ];
|
Loader[] loadersToCreate = new Loader[ batchSizesToCreate.length ];
|
||||||
for ( int i=0; i<batchSizesToCreate.length; i++ ) {
|
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 {
|
else {
|
||||||
return new OneToManyLoader(persister, factory, enabledFilters);
|
return new OneToManyLoader( persister, factory, loadQueryInfluencers );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CollectionInitializer createBatchingCollectionInitializer(
|
public static CollectionInitializer createBatchingCollectionInitializer(
|
||||||
final QueryableCollection persister,
|
final QueryableCollection persister,
|
||||||
final int maxBatchSize,
|
final int maxBatchSize,
|
||||||
final SessionFactoryImplementor factory,
|
final SessionFactoryImplementor factory,
|
||||||
final Map enabledFilters)
|
final LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
|
||||||
throws MappingException {
|
if ( maxBatchSize > 1 ) {
|
||||||
|
|
||||||
if ( maxBatchSize>1 ) {
|
|
||||||
int[] batchSizesToCreate = ArrayHelper.getBatchSizes(maxBatchSize);
|
int[] batchSizesToCreate = ArrayHelper.getBatchSizes(maxBatchSize);
|
||||||
Loader[] loadersToCreate = new Loader[ batchSizesToCreate.length ];
|
Loader[] loadersToCreate = new Loader[ batchSizesToCreate.length ];
|
||||||
for ( int i=0; i<batchSizesToCreate.length; i++ ) {
|
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);
|
return new BatchingCollectionInitializer(persister, batchSizesToCreate, loadersToCreate);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return new BasicCollectionLoader(persister, factory, enabledFilters);
|
return new BasicCollectionLoader( persister, factory, loadQueryInfluencers );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,9 +24,8 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.loader.collection;
|
package org.hibernate.loader.collection;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
import org.hibernate.loader.JoinWalker;
|
import org.hibernate.loader.JoinWalker;
|
||||||
import org.hibernate.util.StringHelper;
|
import org.hibernate.util.StringHelper;
|
||||||
|
|
||||||
|
@ -40,8 +39,8 @@ import org.hibernate.util.StringHelper;
|
||||||
*/
|
*/
|
||||||
public abstract class CollectionJoinWalker extends JoinWalker {
|
public abstract class CollectionJoinWalker extends JoinWalker {
|
||||||
|
|
||||||
public CollectionJoinWalker(SessionFactoryImplementor factory, Map enabledFilters) {
|
public CollectionJoinWalker(SessionFactoryImplementor factory, LoadQueryInfluencers loadQueryInfluencers) {
|
||||||
super( factory, enabledFilters );
|
super( factory, loadQueryInfluencers );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected StringBuffer whereString(String alias, String[] columnNames, String subselect, int batchSize) {
|
protected StringBuffer whereString(String alias, String[] columnNames, String subselect, int batchSize) {
|
||||||
|
|
|
@ -25,11 +25,11 @@
|
||||||
package org.hibernate.loader.collection;
|
package org.hibernate.loader.collection;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.SessionImplementor;
|
import org.hibernate.engine.SessionImplementor;
|
||||||
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
import org.hibernate.loader.OuterJoinLoader;
|
import org.hibernate.loader.OuterJoinLoader;
|
||||||
import org.hibernate.persister.collection.QueryableCollection;
|
import org.hibernate.persister.collection.QueryableCollection;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
|
@ -45,8 +45,11 @@ public class CollectionLoader extends OuterJoinLoader implements CollectionIniti
|
||||||
|
|
||||||
private final QueryableCollection collectionPersister;
|
private final QueryableCollection collectionPersister;
|
||||||
|
|
||||||
public CollectionLoader(QueryableCollection collectionPersister, SessionFactoryImplementor factory, Map enabledFilters) {
|
public CollectionLoader(
|
||||||
super( factory, enabledFilters );
|
QueryableCollection collectionPersister,
|
||||||
|
SessionFactoryImplementor factory,
|
||||||
|
LoadQueryInfluencers loadQueryInfluencers) {
|
||||||
|
super( factory, loadQueryInfluencers );
|
||||||
this.collectionPersister = collectionPersister;
|
this.collectionPersister = collectionPersister;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,11 +27,11 @@ package org.hibernate.loader.collection;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
import org.hibernate.loader.BasicLoader;
|
import org.hibernate.loader.BasicLoader;
|
||||||
import org.hibernate.loader.OuterJoinableAssociation;
|
import org.hibernate.loader.OuterJoinableAssociation;
|
||||||
import org.hibernate.persister.collection.QueryableCollection;
|
import org.hibernate.persister.collection.QueryableCollection;
|
||||||
|
@ -67,10 +67,8 @@ public class OneToManyJoinWalker extends CollectionJoinWalker {
|
||||||
int batchSize,
|
int batchSize,
|
||||||
String subquery,
|
String subquery,
|
||||||
SessionFactoryImplementor factory,
|
SessionFactoryImplementor factory,
|
||||||
Map enabledFilters)
|
LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
|
||||||
throws MappingException {
|
super( factory, loadQueryInfluencers );
|
||||||
|
|
||||||
super(factory, enabledFilters);
|
|
||||||
|
|
||||||
this.oneToManyPersister = oneToManyPersister;
|
this.oneToManyPersister = oneToManyPersister;
|
||||||
|
|
||||||
|
@ -93,7 +91,6 @@ public class OneToManyJoinWalker extends CollectionJoinWalker {
|
||||||
|
|
||||||
initPersisters(allAssociations, LockMode.NONE);
|
initPersisters(allAssociations, LockMode.NONE);
|
||||||
initStatementString(elementPersister, alias, batchSize, subquery);
|
initStatementString(elementPersister, alias, batchSize, subquery);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initStatementString(
|
private void initStatementString(
|
||||||
|
@ -115,7 +112,7 @@ public class OneToManyJoinWalker extends CollectionJoinWalker {
|
||||||
subquery,
|
subquery,
|
||||||
batchSize
|
batchSize
|
||||||
);
|
);
|
||||||
String filter = oneToManyPersister.filterFragment( alias, getEnabledFilters() );
|
String filter = oneToManyPersister.filterFragment( alias, getLoadQueryInfluencers().getEnabledFilters() );
|
||||||
whereString.insert( 0, StringHelper.moveAndToBeginning(filter) );
|
whereString.insert( 0, StringHelper.moveAndToBeginning(filter) );
|
||||||
|
|
||||||
JoinFragment ojf = mergeOuterJoins(associations);
|
JoinFragment ojf = mergeOuterJoins(associations);
|
||||||
|
|
|
@ -24,12 +24,11 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.loader.collection;
|
package org.hibernate.loader.collection;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
import org.hibernate.loader.JoinWalker;
|
import org.hibernate.loader.JoinWalker;
|
||||||
import org.hibernate.persister.collection.QueryableCollection;
|
import org.hibernate.persister.collection.QueryableCollection;
|
||||||
|
|
||||||
|
@ -49,18 +48,16 @@ public class OneToManyLoader extends CollectionLoader {
|
||||||
public OneToManyLoader(
|
public OneToManyLoader(
|
||||||
QueryableCollection oneToManyPersister,
|
QueryableCollection oneToManyPersister,
|
||||||
SessionFactoryImplementor session,
|
SessionFactoryImplementor session,
|
||||||
Map enabledFilters)
|
LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
|
||||||
throws MappingException {
|
this( oneToManyPersister, 1, session, loadQueryInfluencers );
|
||||||
this(oneToManyPersister, 1, session, enabledFilters);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public OneToManyLoader(
|
public OneToManyLoader(
|
||||||
QueryableCollection oneToManyPersister,
|
QueryableCollection oneToManyPersister,
|
||||||
int batchSize,
|
int batchSize,
|
||||||
SessionFactoryImplementor factory,
|
SessionFactoryImplementor factory,
|
||||||
Map enabledFilters)
|
LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
|
||||||
throws MappingException {
|
this( oneToManyPersister, batchSize, null, factory, loadQueryInfluencers );
|
||||||
this(oneToManyPersister, batchSize, null, factory, enabledFilters);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public OneToManyLoader(
|
public OneToManyLoader(
|
||||||
|
@ -68,22 +65,19 @@ public class OneToManyLoader extends CollectionLoader {
|
||||||
int batchSize,
|
int batchSize,
|
||||||
String subquery,
|
String subquery,
|
||||||
SessionFactoryImplementor factory,
|
SessionFactoryImplementor factory,
|
||||||
Map enabledFilters)
|
LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
|
||||||
throws MappingException {
|
super( oneToManyPersister, factory, loadQueryInfluencers );
|
||||||
|
|
||||||
super(oneToManyPersister, factory, enabledFilters);
|
|
||||||
|
|
||||||
JoinWalker walker = new OneToManyJoinWalker(
|
JoinWalker walker = new OneToManyJoinWalker(
|
||||||
oneToManyPersister,
|
oneToManyPersister,
|
||||||
batchSize,
|
batchSize,
|
||||||
subquery,
|
subquery,
|
||||||
factory,
|
factory,
|
||||||
enabledFilters
|
loadQueryInfluencers
|
||||||
);
|
);
|
||||||
initFromWalker( walker );
|
initFromWalker( walker );
|
||||||
|
|
||||||
postInstantiate();
|
postInstantiate();
|
||||||
|
|
||||||
log.debug( "Static select for one-to-many " + oneToManyPersister.getRole() + ": " + getSQLString() );
|
log.debug( "Static select for one-to-many " + oneToManyPersister.getRole() + ": " + getSQLString() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ import org.hibernate.engine.EntityKey;
|
||||||
import org.hibernate.engine.QueryParameters;
|
import org.hibernate.engine.QueryParameters;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.SessionImplementor;
|
import org.hibernate.engine.SessionImplementor;
|
||||||
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
import org.hibernate.persister.collection.QueryableCollection;
|
import org.hibernate.persister.collection.QueryableCollection;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
|
@ -57,10 +58,8 @@ public class SubselectCollectionLoader extends BasicCollectionLoader {
|
||||||
QueryParameters queryParameters,
|
QueryParameters queryParameters,
|
||||||
Map namedParameterLocMap,
|
Map namedParameterLocMap,
|
||||||
SessionFactoryImplementor factory,
|
SessionFactoryImplementor factory,
|
||||||
Map enabledFilters)
|
LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
|
||||||
throws MappingException {
|
super( persister, 1, subquery, factory, loadQueryInfluencers );
|
||||||
|
|
||||||
super(persister, 1, subquery, factory, enabledFilters);
|
|
||||||
|
|
||||||
keys = new Serializable[ entityKeys.size() ];
|
keys = new Serializable[ entityKeys.size() ];
|
||||||
Iterator iter = entityKeys.iterator();
|
Iterator iter = entityKeys.iterator();
|
||||||
|
@ -77,7 +76,7 @@ public class SubselectCollectionLoader extends BasicCollectionLoader {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initialize(Serializable id, SessionImplementor session)
|
public void initialize(Serializable id, SessionImplementor session)
|
||||||
throws HibernateException {
|
throws HibernateException {
|
||||||
loadCollectionSubselect(
|
loadCollectionSubselect(
|
||||||
session,
|
session,
|
||||||
keys,
|
keys,
|
||||||
|
@ -85,7 +84,7 @@ public class SubselectCollectionLoader extends BasicCollectionLoader {
|
||||||
types,
|
types,
|
||||||
namedParameters,
|
namedParameters,
|
||||||
getKeyType()
|
getKeyType()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int[] getNamedParameterLocs(String name) {
|
public int[] getNamedParameterLocs(String name) {
|
||||||
|
|
|
@ -35,6 +35,7 @@ import org.hibernate.engine.EntityKey;
|
||||||
import org.hibernate.engine.QueryParameters;
|
import org.hibernate.engine.QueryParameters;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.SessionImplementor;
|
import org.hibernate.engine.SessionImplementor;
|
||||||
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
import org.hibernate.persister.collection.QueryableCollection;
|
import org.hibernate.persister.collection.QueryableCollection;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
|
@ -57,10 +58,8 @@ public class SubselectOneToManyLoader extends OneToManyLoader {
|
||||||
QueryParameters queryParameters,
|
QueryParameters queryParameters,
|
||||||
Map namedParameterLocMap,
|
Map namedParameterLocMap,
|
||||||
SessionFactoryImplementor factory,
|
SessionFactoryImplementor factory,
|
||||||
Map enabledFilters)
|
LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
|
||||||
throws MappingException {
|
super( persister, 1, subquery, factory, loadQueryInfluencers );
|
||||||
|
|
||||||
super(persister, 1, subquery, factory, enabledFilters);
|
|
||||||
|
|
||||||
keys = new Serializable[ entityKeys.size() ];
|
keys = new Serializable[ entityKeys.size() ];
|
||||||
Iterator iter = entityKeys.iterator();
|
Iterator iter = entityKeys.iterator();
|
||||||
|
@ -73,11 +72,9 @@ public class SubselectOneToManyLoader extends OneToManyLoader {
|
||||||
this.types = queryParameters.getFilteredPositionalParameterTypes();
|
this.types = queryParameters.getFilteredPositionalParameterTypes();
|
||||||
this.values = queryParameters.getFilteredPositionalParameterValues();
|
this.values = queryParameters.getFilteredPositionalParameterValues();
|
||||||
this.namedParameterLocMap = namedParameterLocMap;
|
this.namedParameterLocMap = namedParameterLocMap;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initialize(Serializable id, SessionImplementor session)
|
public void initialize(Serializable id, SessionImplementor session) throws HibernateException {
|
||||||
throws HibernateException {
|
|
||||||
loadCollectionSubselect(
|
loadCollectionSubselect(
|
||||||
session,
|
session,
|
||||||
keys,
|
keys,
|
||||||
|
@ -85,7 +82,7 @@ public class SubselectOneToManyLoader extends OneToManyLoader {
|
||||||
types,
|
types,
|
||||||
namedParameters,
|
namedParameters,
|
||||||
getKeyType()
|
getKeyType()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int[] getNamedParameterLocs(String name) {
|
public int[] getNamedParameterLocs(String name) {
|
||||||
|
|
|
@ -26,7 +26,6 @@ package org.hibernate.loader.criteria;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.hibernate.Criteria;
|
import org.hibernate.Criteria;
|
||||||
|
@ -35,6 +34,7 @@ import org.hibernate.LockMode;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.engine.CascadeStyle;
|
import org.hibernate.engine.CascadeStyle;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
import org.hibernate.impl.CriteriaImpl;
|
import org.hibernate.impl.CriteriaImpl;
|
||||||
import org.hibernate.loader.AbstractEntityJoinWalker;
|
import org.hibernate.loader.AbstractEntityJoinWalker;
|
||||||
import org.hibernate.persister.entity.Joinable;
|
import org.hibernate.persister.entity.Joinable;
|
||||||
|
@ -78,8 +78,8 @@ public class CriteriaJoinWalker extends AbstractEntityJoinWalker {
|
||||||
final SessionFactoryImplementor factory,
|
final SessionFactoryImplementor factory,
|
||||||
final CriteriaImpl criteria,
|
final CriteriaImpl criteria,
|
||||||
final String rootEntityName,
|
final String rootEntityName,
|
||||||
final Map enabledFilters) {
|
final LoadQueryInfluencers loadQueryInfluencers) {
|
||||||
this(persister, translator, factory, criteria, rootEntityName, enabledFilters, null);
|
this( persister, translator, factory, criteria, rootEntityName, loadQueryInfluencers, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
public CriteriaJoinWalker(
|
public CriteriaJoinWalker(
|
||||||
|
@ -88,9 +88,9 @@ public class CriteriaJoinWalker extends AbstractEntityJoinWalker {
|
||||||
final SessionFactoryImplementor factory,
|
final SessionFactoryImplementor factory,
|
||||||
final CriteriaImpl criteria,
|
final CriteriaImpl criteria,
|
||||||
final String rootEntityName,
|
final String rootEntityName,
|
||||||
final Map enabledFilters,
|
final LoadQueryInfluencers loadQueryInfluencers,
|
||||||
final String alias) {
|
final String alias) {
|
||||||
super(persister, factory, enabledFilters, alias);
|
super( persister, factory, loadQueryInfluencers, alias );
|
||||||
|
|
||||||
this.translator = translator;
|
this.translator = translator;
|
||||||
|
|
||||||
|
@ -119,16 +119,17 @@ public class CriteriaJoinWalker extends AbstractEntityJoinWalker {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int getJoinType(
|
protected int getJoinType(
|
||||||
AssociationType type,
|
OuterJoinLoadable persister,
|
||||||
FetchMode config,
|
final String path,
|
||||||
String path,
|
int propertyNumber,
|
||||||
|
AssociationType associationType,
|
||||||
|
FetchMode metadataFetchMode,
|
||||||
|
CascadeStyle metadataCascadeStyle,
|
||||||
String lhsTable,
|
String lhsTable,
|
||||||
String[] lhsColumns,
|
String[] lhsColumns,
|
||||||
boolean nullable,
|
final boolean nullable,
|
||||||
int currentDepth, CascadeStyle cascadeStyle)
|
final int currentDepth) throws MappingException {
|
||||||
throws MappingException {
|
if ( translator.isJoin( path ) ) {
|
||||||
|
|
||||||
if ( translator.isJoin(path) ) {
|
|
||||||
return translator.getJoinType( path );
|
return translator.getJoinType( path );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -136,23 +137,30 @@ public class CriteriaJoinWalker extends AbstractEntityJoinWalker {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
FetchMode fetchMode = translator.getRootCriteria()
|
FetchMode fetchMode = translator.getRootCriteria().getFetchMode( path );
|
||||||
.getFetchMode(path);
|
if ( isDefaultFetchMode( fetchMode ) ) {
|
||||||
if ( isDefaultFetchMode(fetchMode) ) {
|
if ( isJoinFetchEnabledByProfile( persister, path, propertyNumber ) ) {
|
||||||
return super.getJoinType(
|
return getJoinType( nullable, currentDepth );
|
||||||
type,
|
}
|
||||||
config,
|
else {
|
||||||
path,
|
return super.getJoinType(
|
||||||
lhsTable,
|
persister,
|
||||||
lhsColumns,
|
path,
|
||||||
nullable,
|
propertyNumber,
|
||||||
currentDepth, cascadeStyle
|
associationType,
|
||||||
|
metadataFetchMode,
|
||||||
|
metadataCascadeStyle,
|
||||||
|
lhsTable,
|
||||||
|
lhsColumns,
|
||||||
|
nullable,
|
||||||
|
currentDepth
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ( fetchMode==FetchMode.JOIN ) {
|
if ( fetchMode == FetchMode.JOIN ) {
|
||||||
isDuplicateAssociation(lhsTable, lhsColumns, type); //deliberately ignore return value!
|
isDuplicateAssociation( lhsTable, lhsColumns, associationType ); //deliberately ignore return value!
|
||||||
return getJoinType(nullable, currentDepth);
|
return getJoinType( nullable, currentDepth );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -172,7 +180,7 @@ public class CriteriaJoinWalker extends AbstractEntityJoinWalker {
|
||||||
*/
|
*/
|
||||||
protected String getWhereFragment() throws MappingException {
|
protected String getWhereFragment() throws MappingException {
|
||||||
return super.getWhereFragment() +
|
return super.getWhereFragment() +
|
||||||
( (Queryable) getPersister() ).filterFragment( getAlias(), getEnabledFilters() );
|
( (Queryable) getPersister() ).filterFragment( getAlias(), getLoadQueryInfluencers().getEnabledFilters() );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String generateTableAlias(int n, String path, Joinable joinable) {
|
protected String generateTableAlias(int n, String path, Joinable joinable) {
|
||||||
|
|
|
@ -30,7 +30,6 @@ import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.Iterator;
|
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
|
@ -41,6 +40,7 @@ import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.engine.QueryParameters;
|
import org.hibernate.engine.QueryParameters;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.SessionImplementor;
|
import org.hibernate.engine.SessionImplementor;
|
||||||
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
import org.hibernate.impl.CriteriaImpl;
|
import org.hibernate.impl.CriteriaImpl;
|
||||||
import org.hibernate.loader.OuterJoinLoader;
|
import org.hibernate.loader.OuterJoinLoader;
|
||||||
import org.hibernate.persister.entity.OuterJoinLoadable;
|
import org.hibernate.persister.entity.OuterJoinLoadable;
|
||||||
|
@ -75,9 +75,8 @@ public class CriteriaLoader extends OuterJoinLoader {
|
||||||
final SessionFactoryImplementor factory,
|
final SessionFactoryImplementor factory,
|
||||||
final CriteriaImpl criteria,
|
final CriteriaImpl criteria,
|
||||||
final String rootEntityName,
|
final String rootEntityName,
|
||||||
final Map enabledFilters)
|
final LoadQueryInfluencers loadQueryInfluencers) throws HibernateException {
|
||||||
throws HibernateException {
|
super( factory, loadQueryInfluencers );
|
||||||
super(factory, enabledFilters);
|
|
||||||
|
|
||||||
translator = new CriteriaQueryTranslator(
|
translator = new CriteriaQueryTranslator(
|
||||||
factory,
|
factory,
|
||||||
|
@ -94,7 +93,7 @@ public class CriteriaLoader extends OuterJoinLoader {
|
||||||
factory,
|
factory,
|
||||||
criteria,
|
criteria,
|
||||||
rootEntityName,
|
rootEntityName,
|
||||||
enabledFilters
|
loadQueryInfluencers
|
||||||
);
|
);
|
||||||
|
|
||||||
initFromWalker(walker);
|
initFromWalker(walker);
|
||||||
|
|
|
@ -29,12 +29,14 @@ import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.SessionImplementor;
|
import org.hibernate.engine.SessionImplementor;
|
||||||
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
import org.hibernate.loader.OuterJoinLoader;
|
import org.hibernate.loader.OuterJoinLoader;
|
||||||
import org.hibernate.persister.entity.OuterJoinLoadable;
|
import org.hibernate.persister.entity.OuterJoinLoadable;
|
||||||
import org.hibernate.transform.ResultTransformer;
|
import org.hibernate.transform.ResultTransformer;
|
||||||
|
@ -52,8 +54,8 @@ public abstract class AbstractEntityLoader extends OuterJoinLoader
|
||||||
OuterJoinLoadable persister,
|
OuterJoinLoadable persister,
|
||||||
Type uniqueKeyType,
|
Type uniqueKeyType,
|
||||||
SessionFactoryImplementor factory,
|
SessionFactoryImplementor factory,
|
||||||
Map enabledFilters) {
|
LoadQueryInfluencers loadQueryInfluencers) {
|
||||||
super( factory, enabledFilters );
|
super( factory, loadQueryInfluencers );
|
||||||
this.uniqueKeyType = uniqueKeyType;
|
this.uniqueKeyType = uniqueKeyType;
|
||||||
this.entityName = persister.getEntityName();
|
this.entityName = persister.getEntityName();
|
||||||
this.persister = persister;
|
this.persister = persister;
|
||||||
|
|
|
@ -28,12 +28,14 @@ import java.io.Serializable;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.SessionImplementor;
|
import org.hibernate.engine.SessionImplementor;
|
||||||
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
import org.hibernate.loader.Loader;
|
import org.hibernate.loader.Loader;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.persister.entity.OuterJoinLoadable;
|
import org.hibernate.persister.entity.OuterJoinLoadable;
|
||||||
|
@ -111,19 +113,18 @@ public class BatchingEntityLoader implements UniqueEntityLoader {
|
||||||
final int maxBatchSize,
|
final int maxBatchSize,
|
||||||
final LockMode lockMode,
|
final LockMode lockMode,
|
||||||
final SessionFactoryImplementor factory,
|
final SessionFactoryImplementor factory,
|
||||||
final Map enabledFilters)
|
final LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
|
||||||
throws MappingException {
|
|
||||||
|
|
||||||
if ( maxBatchSize>1 ) {
|
if ( maxBatchSize>1 ) {
|
||||||
int[] batchSizesToCreate = ArrayHelper.getBatchSizes(maxBatchSize);
|
int[] batchSizesToCreate = ArrayHelper.getBatchSizes(maxBatchSize);
|
||||||
Loader[] loadersToCreate = new Loader[ batchSizesToCreate.length ];
|
Loader[] loadersToCreate = new Loader[ batchSizesToCreate.length ];
|
||||||
for ( int i=0; i<batchSizesToCreate.length; i++ ) {
|
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);
|
return new BatchingEntityLoader(persister, batchSizesToCreate, loadersToCreate);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return new EntityLoader(persister, lockMode, factory, enabledFilters);
|
return new EntityLoader(persister, lockMode, factory, loadQueryInfluencers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ import org.hibernate.MappingException;
|
||||||
import org.hibernate.engine.CascadeStyle;
|
import org.hibernate.engine.CascadeStyle;
|
||||||
import org.hibernate.engine.CascadingAction;
|
import org.hibernate.engine.CascadingAction;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
import org.hibernate.loader.AbstractEntityJoinWalker;
|
import org.hibernate.loader.AbstractEntityJoinWalker;
|
||||||
import org.hibernate.persister.entity.OuterJoinLoadable;
|
import org.hibernate.persister.entity.OuterJoinLoadable;
|
||||||
import org.hibernate.type.AssociationType;
|
import org.hibernate.type.AssociationType;
|
||||||
|
@ -41,7 +42,7 @@ public class CascadeEntityJoinWalker extends AbstractEntityJoinWalker {
|
||||||
|
|
||||||
public CascadeEntityJoinWalker(OuterJoinLoadable persister, CascadingAction action, SessionFactoryImplementor factory)
|
public CascadeEntityJoinWalker(OuterJoinLoadable persister, CascadingAction action, SessionFactoryImplementor factory)
|
||||||
throws MappingException {
|
throws MappingException {
|
||||||
super( persister, factory, CollectionHelper.EMPTY_MAP );
|
super( persister, factory, LoadQueryInfluencers.NONE );
|
||||||
this.cascadeAction = action;
|
this.cascadeAction = action;
|
||||||
StringBuffer whereCondition = whereString( getAlias(), persister.getIdentifierColumnNames(), 1 )
|
StringBuffer whereCondition = whereString( getAlias(), persister.getIdentifierColumnNames(), 1 )
|
||||||
//include the discriminator and class-level where, but not filters
|
//include the discriminator and class-level where, but not filters
|
||||||
|
|
|
@ -27,29 +27,28 @@ package org.hibernate.loader.entity;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.engine.CascadingAction;
|
import org.hibernate.engine.CascadingAction;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
import org.hibernate.loader.JoinWalker;
|
import org.hibernate.loader.JoinWalker;
|
||||||
import org.hibernate.persister.entity.OuterJoinLoadable;
|
import org.hibernate.persister.entity.OuterJoinLoadable;
|
||||||
import org.hibernate.util.CollectionHelper;
|
|
||||||
|
|
||||||
public class CascadeEntityLoader extends AbstractEntityLoader {
|
public class CascadeEntityLoader extends AbstractEntityLoader {
|
||||||
|
|
||||||
public CascadeEntityLoader(
|
public CascadeEntityLoader(
|
||||||
OuterJoinLoadable persister,
|
OuterJoinLoadable persister,
|
||||||
CascadingAction action,
|
CascadingAction action,
|
||||||
SessionFactoryImplementor factory)
|
SessionFactoryImplementor factory) throws MappingException {
|
||||||
throws MappingException {
|
|
||||||
super(
|
super(
|
||||||
persister,
|
persister,
|
||||||
persister.getIdentifierType(),
|
persister.getIdentifierType(),
|
||||||
factory,
|
factory,
|
||||||
CollectionHelper.EMPTY_MAP
|
LoadQueryInfluencers.NONE
|
||||||
);
|
);
|
||||||
|
|
||||||
JoinWalker walker = new CascadeEntityJoinWalker(
|
JoinWalker walker = new CascadeEntityJoinWalker(
|
||||||
persister,
|
persister,
|
||||||
action,
|
action,
|
||||||
factory
|
factory
|
||||||
);
|
);
|
||||||
initFromWalker( walker );
|
initFromWalker( walker );
|
||||||
|
|
||||||
postInstantiate();
|
postInstantiate();
|
||||||
|
|
|
@ -27,7 +27,6 @@ package org.hibernate.loader.entity;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -36,6 +35,7 @@ import org.hibernate.LockMode;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.SessionImplementor;
|
import org.hibernate.engine.SessionImplementor;
|
||||||
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
import org.hibernate.loader.JoinWalker;
|
import org.hibernate.loader.JoinWalker;
|
||||||
import org.hibernate.loader.OuterJoinLoader;
|
import org.hibernate.loader.OuterJoinLoader;
|
||||||
import org.hibernate.persister.collection.QueryableCollection;
|
import org.hibernate.persister.collection.QueryableCollection;
|
||||||
|
@ -61,9 +61,8 @@ public class CollectionElementLoader extends OuterJoinLoader {
|
||||||
public CollectionElementLoader(
|
public CollectionElementLoader(
|
||||||
QueryableCollection collectionPersister,
|
QueryableCollection collectionPersister,
|
||||||
SessionFactoryImplementor factory,
|
SessionFactoryImplementor factory,
|
||||||
Map enabledFilters)
|
LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
|
||||||
throws MappingException {
|
super( factory, loadQueryInfluencers );
|
||||||
super(factory, enabledFilters);
|
|
||||||
|
|
||||||
this.keyType = collectionPersister.getKeyType();
|
this.keyType = collectionPersister.getKeyType();
|
||||||
this.indexType = collectionPersister.getIndexType();
|
this.indexType = collectionPersister.getIndexType();
|
||||||
|
@ -79,7 +78,7 @@ public class CollectionElementLoader extends OuterJoinLoader {
|
||||||
1,
|
1,
|
||||||
LockMode.NONE,
|
LockMode.NONE,
|
||||||
factory,
|
factory,
|
||||||
enabledFilters
|
loadQueryInfluencers
|
||||||
);
|
);
|
||||||
initFromWalker( walker );
|
initFromWalker( walker );
|
||||||
|
|
||||||
|
@ -130,5 +129,4 @@ public class CollectionElementLoader extends OuterJoinLoader {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -25,13 +25,16 @@
|
||||||
package org.hibernate.loader.entity;
|
package org.hibernate.loader.entity;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Iterator;
|
||||||
|
|
||||||
import org.hibernate.FetchMode;
|
import org.hibernate.FetchMode;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.engine.CascadeStyle;
|
import org.hibernate.engine.CascadeStyle;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
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.loader.AbstractEntityJoinWalker;
|
||||||
import org.hibernate.persister.entity.OuterJoinLoadable;
|
import org.hibernate.persister.entity.OuterJoinLoadable;
|
||||||
import org.hibernate.type.AssociationType;
|
import org.hibernate.type.AssociationType;
|
||||||
|
@ -52,28 +55,47 @@ public class EntityJoinWalker extends AbstractEntityJoinWalker {
|
||||||
int batchSize,
|
int batchSize,
|
||||||
LockMode lockMode,
|
LockMode lockMode,
|
||||||
SessionFactoryImplementor factory,
|
SessionFactoryImplementor factory,
|
||||||
Map enabledFilters)
|
LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
|
||||||
throws MappingException {
|
super( persister, factory, loadQueryInfluencers );
|
||||||
super(persister, factory, enabledFilters);
|
|
||||||
|
|
||||||
this.lockMode = lockMode;
|
this.lockMode = lockMode;
|
||||||
|
|
||||||
StringBuffer whereCondition = whereString( getAlias(), uniqueKey, batchSize )
|
StringBuffer whereCondition = whereString( getAlias(), uniqueKey, batchSize )
|
||||||
//include the discriminator and class-level where, but not filters
|
//include the discriminator and class-level where, but not filters
|
||||||
.append( persister.filterFragment( getAlias(), Collections.EMPTY_MAP ) );
|
.append( persister.filterFragment( getAlias(), Collections.EMPTY_MAP ) );
|
||||||
|
|
||||||
initAll( whereCondition.toString(), "", lockMode );
|
initAll( whereCondition.toString(), "", lockMode );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected int getJoinType(
|
||||||
* Disable outer join fetching if this loader obtains an
|
OuterJoinLoadable persister,
|
||||||
* upgrade lock mode
|
String path,
|
||||||
*/
|
int propertyNumber,
|
||||||
protected boolean isJoinedFetchEnabled(AssociationType type, FetchMode config, CascadeStyle cascadeStyle) {
|
AssociationType associationType,
|
||||||
return lockMode.greaterThan(LockMode.READ) ?
|
FetchMode metadataFetchMode,
|
||||||
false :
|
CascadeStyle metadataCascadeStyle,
|
||||||
super.isJoinedFetchEnabled(type, config, cascadeStyle);
|
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() {
|
public String getComment() {
|
||||||
|
|
|
@ -25,12 +25,14 @@
|
||||||
package org.hibernate.loader.entity;
|
package org.hibernate.loader.entity;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.SessionImplementor;
|
import org.hibernate.engine.SessionImplementor;
|
||||||
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
import org.hibernate.loader.JoinWalker;
|
import org.hibernate.loader.JoinWalker;
|
||||||
import org.hibernate.persister.entity.OuterJoinLoadable;
|
import org.hibernate.persister.entity.OuterJoinLoadable;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
|
@ -51,9 +53,8 @@ public class EntityLoader extends AbstractEntityLoader {
|
||||||
OuterJoinLoadable persister,
|
OuterJoinLoadable persister,
|
||||||
LockMode lockMode,
|
LockMode lockMode,
|
||||||
SessionFactoryImplementor factory,
|
SessionFactoryImplementor factory,
|
||||||
Map enabledFilters)
|
LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
|
||||||
throws MappingException {
|
this( persister, 1, lockMode, factory, loadQueryInfluencers );
|
||||||
this(persister, 1, lockMode, factory, enabledFilters);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public EntityLoader(
|
public EntityLoader(
|
||||||
|
@ -61,16 +62,15 @@ public class EntityLoader extends AbstractEntityLoader {
|
||||||
int batchSize,
|
int batchSize,
|
||||||
LockMode lockMode,
|
LockMode lockMode,
|
||||||
SessionFactoryImplementor factory,
|
SessionFactoryImplementor factory,
|
||||||
Map enabledFilters)
|
LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
|
||||||
throws MappingException {
|
this(
|
||||||
this(
|
persister,
|
||||||
persister,
|
|
||||||
persister.getIdentifierColumnNames(),
|
persister.getIdentifierColumnNames(),
|
||||||
persister.getIdentifierType(),
|
persister.getIdentifierType(),
|
||||||
batchSize,
|
batchSize,
|
||||||
lockMode,
|
lockMode,
|
||||||
factory,
|
factory,
|
||||||
enabledFilters
|
loadQueryInfluencers
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,9 +81,8 @@ public class EntityLoader extends AbstractEntityLoader {
|
||||||
int batchSize,
|
int batchSize,
|
||||||
LockMode lockMode,
|
LockMode lockMode,
|
||||||
SessionFactoryImplementor factory,
|
SessionFactoryImplementor factory,
|
||||||
Map enabledFilters)
|
LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
|
||||||
throws MappingException {
|
super( persister, uniqueKeyType, factory, loadQueryInfluencers );
|
||||||
super(persister, uniqueKeyType, factory, enabledFilters);
|
|
||||||
|
|
||||||
JoinWalker walker = new EntityJoinWalker(
|
JoinWalker walker = new EntityJoinWalker(
|
||||||
persister,
|
persister,
|
||||||
|
@ -91,8 +90,8 @@ public class EntityLoader extends AbstractEntityLoader {
|
||||||
batchSize,
|
batchSize,
|
||||||
lockMode,
|
lockMode,
|
||||||
factory,
|
factory,
|
||||||
enabledFilters
|
loadQueryInfluencers
|
||||||
);
|
);
|
||||||
initFromWalker( walker );
|
initFromWalker( walker );
|
||||||
|
|
||||||
postInstantiate();
|
postInstantiate();
|
||||||
|
@ -103,9 +102,10 @@ public class EntityLoader extends AbstractEntityLoader {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object loadByUniqueKey(SessionImplementor session, Object key)
|
public Object loadByUniqueKey(
|
||||||
throws HibernateException {
|
SessionImplementor session,
|
||||||
return load(session, key, null, null);
|
Object key) throws HibernateException {
|
||||||
|
return load( session, key, null, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isSingleRowLoader() {
|
protected boolean isSingleRowLoader() {
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -58,6 +58,7 @@ import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.SessionImplementor;
|
import org.hibernate.engine.SessionImplementor;
|
||||||
import org.hibernate.engine.SubselectFetch;
|
import org.hibernate.engine.SubselectFetch;
|
||||||
import org.hibernate.engine.ExecuteUpdateResultCheckStyle;
|
import org.hibernate.engine.ExecuteUpdateResultCheckStyle;
|
||||||
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
import org.hibernate.exception.JDBCExceptionHelper;
|
import org.hibernate.exception.JDBCExceptionHelper;
|
||||||
import org.hibernate.exception.SQLExceptionConverter;
|
import org.hibernate.exception.SQLExceptionConverter;
|
||||||
import org.hibernate.id.IdentifierGenerator;
|
import org.hibernate.id.IdentifierGenerator;
|
||||||
|
@ -561,7 +562,7 @@ public abstract class AbstractCollectionPersister
|
||||||
|
|
||||||
public void postInstantiate() throws MappingException {
|
public void postInstantiate() throws MappingException {
|
||||||
initializer = queryLoaderName == null ?
|
initializer = queryLoaderName == null ?
|
||||||
createCollectionInitializer( CollectionHelper.EMPTY_MAP ) :
|
createCollectionInitializer( LoadQueryInfluencers.NONE ) :
|
||||||
new NamedQueryCollectionInitializer( queryLoaderName, this );
|
new NamedQueryCollectionInitializer( queryLoaderName, this );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -601,7 +602,7 @@ public abstract class AbstractCollectionPersister
|
||||||
return initializer;
|
return initializer;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return createCollectionInitializer( session.getEnabledFilters() );
|
return createCollectionInitializer( session.getLoadQueryInfluencers() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -637,7 +638,7 @@ public abstract class AbstractCollectionPersister
|
||||||
|
|
||||||
protected abstract CollectionInitializer createSubselectInitializer(SubselectFetch subselect, SessionImplementor session);
|
protected abstract CollectionInitializer createSubselectInitializer(SubselectFetch subselect, SessionImplementor session);
|
||||||
|
|
||||||
protected abstract CollectionInitializer createCollectionInitializer(Map enabledFilters)
|
protected abstract CollectionInitializer createCollectionInitializer(LoadQueryInfluencers loadQueryInfluencers)
|
||||||
throws MappingException;
|
throws MappingException;
|
||||||
|
|
||||||
public CollectionRegionAccessStrategy getCacheAccessStrategy() {
|
public CollectionRegionAccessStrategy getCacheAccessStrategy() {
|
||||||
|
|
|
@ -42,6 +42,7 @@ import org.hibernate.collection.PersistentCollection;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.SessionImplementor;
|
import org.hibernate.engine.SessionImplementor;
|
||||||
import org.hibernate.engine.SubselectFetch;
|
import org.hibernate.engine.SubselectFetch;
|
||||||
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
import org.hibernate.exception.JDBCExceptionHelper;
|
import org.hibernate.exception.JDBCExceptionHelper;
|
||||||
import org.hibernate.loader.collection.BatchingCollectionInitializer;
|
import org.hibernate.loader.collection.BatchingCollectionInitializer;
|
||||||
import org.hibernate.loader.collection.CollectionInitializer;
|
import org.hibernate.loader.collection.CollectionInitializer;
|
||||||
|
@ -315,9 +316,9 @@ public class BasicCollectionPersister extends AbstractCollectionPersister {
|
||||||
*
|
*
|
||||||
* @see org.hibernate.loader.collection.BasicCollectionLoader
|
* @see org.hibernate.loader.collection.BasicCollectionLoader
|
||||||
*/
|
*/
|
||||||
protected CollectionInitializer createCollectionInitializer(java.util.Map enabledFilters)
|
protected CollectionInitializer createCollectionInitializer(LoadQueryInfluencers loadQueryInfluencers)
|
||||||
throws MappingException {
|
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) {
|
public String fromJoinFragment(String alias, boolean innerJoin, boolean includeSubclasses) {
|
||||||
|
@ -336,8 +337,8 @@ public class BasicCollectionPersister extends AbstractCollectionPersister {
|
||||||
subselect.getQueryParameters(),
|
subselect.getQueryParameters(),
|
||||||
subselect.getNamedParameterLocMap(),
|
subselect.getNamedParameterLocMap(),
|
||||||
session.getFactory(),
|
session.getFactory(),
|
||||||
session.getEnabledFilters()
|
session.getLoadQueryInfluencers()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ import org.hibernate.collection.PersistentCollection;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.SessionImplementor;
|
import org.hibernate.engine.SessionImplementor;
|
||||||
import org.hibernate.engine.SubselectFetch;
|
import org.hibernate.engine.SubselectFetch;
|
||||||
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
import org.hibernate.exception.JDBCExceptionHelper;
|
import org.hibernate.exception.JDBCExceptionHelper;
|
||||||
import org.hibernate.loader.collection.BatchingCollectionInitializer;
|
import org.hibernate.loader.collection.BatchingCollectionInitializer;
|
||||||
import org.hibernate.loader.collection.CollectionInitializer;
|
import org.hibernate.loader.collection.CollectionInitializer;
|
||||||
|
@ -338,8 +339,9 @@ public class OneToManyPersister extends AbstractCollectionPersister {
|
||||||
*
|
*
|
||||||
* @see org.hibernate.loader.collection.OneToManyLoader
|
* @see org.hibernate.loader.collection.OneToManyLoader
|
||||||
*/
|
*/
|
||||||
protected CollectionInitializer createCollectionInitializer(java.util.Map enabledFilters) throws MappingException {
|
protected CollectionInitializer createCollectionInitializer(LoadQueryInfluencers loadQueryInfluencers)
|
||||||
return BatchingCollectionInitializer.createBatchingOneToManyInitializer( this, batchSize, getFactory(), enabledFilters );
|
throws MappingException {
|
||||||
|
return BatchingCollectionInitializer.createBatchingOneToManyInitializer( this, batchSize, getFactory(), loadQueryInfluencers );
|
||||||
}
|
}
|
||||||
|
|
||||||
public String fromJoinFragment(String alias,
|
public String fromJoinFragment(String alias,
|
||||||
|
@ -375,12 +377,12 @@ public class OneToManyPersister extends AbstractCollectionPersister {
|
||||||
subselect.getQueryParameters(),
|
subselect.getQueryParameters(),
|
||||||
subselect.getNamedParameterLocMap(),
|
subselect.getNamedParameterLocMap(),
|
||||||
session.getFactory(),
|
session.getFactory(),
|
||||||
session.getEnabledFilters()
|
session.getLoadQueryInfluencers()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getElementByIndex(Serializable key, Object index, SessionImplementor session, Object owner) {
|
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) );
|
.loadElement( session, key, incrementIndexByBase(index) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,6 @@ import org.hibernate.jdbc.Expectation;
|
||||||
import org.hibernate.jdbc.Expectations;
|
import org.hibernate.jdbc.Expectations;
|
||||||
import org.hibernate.jdbc.TooManyRowsAffectedException;
|
import org.hibernate.jdbc.TooManyRowsAffectedException;
|
||||||
import org.hibernate.dialect.lock.LockingStrategy;
|
import org.hibernate.dialect.lock.LockingStrategy;
|
||||||
import org.hibernate.cache.CacheConcurrencyStrategy;
|
|
||||||
import org.hibernate.cache.CacheKey;
|
import org.hibernate.cache.CacheKey;
|
||||||
import org.hibernate.cache.access.EntityRegionAccessStrategy;
|
import org.hibernate.cache.access.EntityRegionAccessStrategy;
|
||||||
import org.hibernate.cache.entry.CacheEntry;
|
import org.hibernate.cache.entry.CacheEntry;
|
||||||
|
@ -69,6 +68,7 @@ import org.hibernate.engine.Versioning;
|
||||||
import org.hibernate.engine.ExecuteUpdateResultCheckStyle;
|
import org.hibernate.engine.ExecuteUpdateResultCheckStyle;
|
||||||
import org.hibernate.engine.EntityKey;
|
import org.hibernate.engine.EntityKey;
|
||||||
import org.hibernate.engine.ValueInclusion;
|
import org.hibernate.engine.ValueInclusion;
|
||||||
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
import org.hibernate.exception.JDBCExceptionHelper;
|
import org.hibernate.exception.JDBCExceptionHelper;
|
||||||
import org.hibernate.id.IdentifierGenerator;
|
import org.hibernate.id.IdentifierGenerator;
|
||||||
import org.hibernate.id.PostInsertIdentifierGenerator;
|
import org.hibernate.id.PostInsertIdentifierGenerator;
|
||||||
|
@ -109,7 +109,6 @@ import org.hibernate.type.Type;
|
||||||
import org.hibernate.type.TypeFactory;
|
import org.hibernate.type.TypeFactory;
|
||||||
import org.hibernate.type.VersionType;
|
import org.hibernate.type.VersionType;
|
||||||
import org.hibernate.util.ArrayHelper;
|
import org.hibernate.util.ArrayHelper;
|
||||||
import org.hibernate.util.CollectionHelper;
|
|
||||||
import org.hibernate.util.FilterHelper;
|
import org.hibernate.util.FilterHelper;
|
||||||
import org.hibernate.util.StringHelper;
|
import org.hibernate.util.StringHelper;
|
||||||
|
|
||||||
|
@ -196,6 +195,8 @@ public abstract class AbstractEntityPersister
|
||||||
// dynamic filters attached to the class-level
|
// dynamic filters attached to the class-level
|
||||||
private final FilterHelper filterHelper;
|
private final FilterHelper filterHelper;
|
||||||
|
|
||||||
|
private final Set affectingFetchProfileNames = new HashSet();
|
||||||
|
|
||||||
private final Map uniqueKeyLoaders = new HashMap();
|
private final Map uniqueKeyLoaders = new HashMap();
|
||||||
private final Map lockers = new HashMap();
|
private final Map lockers = new HashMap();
|
||||||
private final Map loaders = new HashMap();
|
private final Map loaders = new HashMap();
|
||||||
|
@ -1667,26 +1668,27 @@ public abstract class AbstractEntityPersister
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object loadByUniqueKey(String propertyName, Object uniqueKey, SessionImplementor session)
|
public Object loadByUniqueKey(
|
||||||
throws HibernateException {
|
String propertyName,
|
||||||
return getAppropriateUniqueKeyLoader( propertyName, session.getEnabledFilters() )
|
Object uniqueKey,
|
||||||
.loadByUniqueKey( session, uniqueKey );
|
SessionImplementor session) throws HibernateException {
|
||||||
|
return getAppropriateUniqueKeyLoader( propertyName, session ).loadByUniqueKey( session, uniqueKey );
|
||||||
}
|
}
|
||||||
|
|
||||||
private EntityLoader getAppropriateUniqueKeyLoader(String propertyName, Map enabledFilters) {
|
private EntityLoader getAppropriateUniqueKeyLoader(String propertyName, SessionImplementor session) {
|
||||||
|
final boolean useStaticLoader = !session.getLoadQueryInfluencers().hasEnabledFilters()
|
||||||
final boolean useStaticLoader = ( enabledFilters == null || enabledFilters.isEmpty() )
|
&& !session.getLoadQueryInfluencers().hasEnabledFetchProfiles()
|
||||||
&& propertyName.indexOf('.')<0; //ugly little workaround for fact that createUniqueKeyLoaders() does not handle component properties
|
&& propertyName.indexOf('.')<0; //ugly little workaround for fact that createUniqueKeyLoaders() does not handle component properties
|
||||||
|
|
||||||
if ( useStaticLoader ) {
|
if ( useStaticLoader ) {
|
||||||
return (EntityLoader) uniqueKeyLoaders.get( propertyName );
|
return ( EntityLoader ) uniqueKeyLoaders.get( propertyName );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return createUniqueKeyLoader(
|
return createUniqueKeyLoader(
|
||||||
propertyMapping.toType(propertyName),
|
propertyMapping.toType( propertyName ),
|
||||||
propertyMapping.toColumns(propertyName),
|
propertyMapping.toColumns( propertyName ),
|
||||||
enabledFilters
|
session.getLoadQueryInfluencers()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1705,21 +1707,31 @@ public abstract class AbstractEntityPersister
|
||||||
createUniqueKeyLoader(
|
createUniqueKeyLoader(
|
||||||
propertyTypes[i],
|
propertyTypes[i],
|
||||||
getPropertyColumnNames( i ),
|
getPropertyColumnNames( i ),
|
||||||
CollectionHelper.EMPTY_MAP
|
LoadQueryInfluencers.NONE
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
//TODO: create uk loaders for component properties
|
//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() ) {
|
if ( uniqueKeyType.isEntityType() ) {
|
||||||
String className = ( ( EntityType ) uniqueKeyType ).getAssociatedEntityName();
|
String className = ( ( EntityType ) uniqueKeyType ).getAssociatedEntityName();
|
||||||
uniqueKeyType = getFactory().getEntityPersister( className ).getIdentifierType();
|
uniqueKeyType = getFactory().getEntityPersister( className ).getIdentifierType();
|
||||||
}
|
}
|
||||||
|
return new EntityLoader(
|
||||||
return new EntityLoader( this, columns, uniqueKeyType, 1, LockMode.NONE, getFactory(), enabledFilters );
|
this,
|
||||||
|
columns,
|
||||||
|
uniqueKeyType,
|
||||||
|
1,
|
||||||
|
LockMode.NONE,
|
||||||
|
getFactory(),
|
||||||
|
loadQueryInfluencers
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getSQLWhereString(String alias) {
|
protected String getSQLWhereString(String alias) {
|
||||||
|
@ -1770,13 +1782,21 @@ public abstract class AbstractEntityPersister
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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?
|
//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 {
|
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 {
|
protected boolean check(int rows, Serializable id, int tableNumber, Expectation expectation, PreparedStatement statement) throws HibernateException {
|
||||||
|
@ -3072,21 +3092,49 @@ public abstract class AbstractEntityPersister
|
||||||
return loader.load( id, optionalObject, session );
|
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) {
|
private UniqueEntityLoader getAppropriateLoader(LockMode lockMode, SessionImplementor session) {
|
||||||
final Map enabledFilters = session.getEnabledFilters();
|
|
||||||
if ( queryLoader != null ) {
|
if ( queryLoader != null ) {
|
||||||
|
// if the user specified a custom query loader we need to that
|
||||||
|
// regardless of any other consideration
|
||||||
return queryLoader;
|
return queryLoader;
|
||||||
}
|
}
|
||||||
else if ( enabledFilters == null || enabledFilters.isEmpty() ) {
|
else if ( isAffectedByEnabledFilters( session ) ) {
|
||||||
if ( session.getFetchProfile()!=null && LockMode.UPGRADE.greaterThan(lockMode) ) {
|
// because filters affect the rows returned (because they add
|
||||||
return (UniqueEntityLoader) loaders.get( session.getFetchProfile() );
|
// restirctions) these need to be next in precendence
|
||||||
}
|
return createEntityLoader( lockMode, session.getLoadQueryInfluencers() );
|
||||||
else {
|
}
|
||||||
return (UniqueEntityLoader) loaders.get( lockMode );
|
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 {
|
else {
|
||||||
return createEntityLoader( lockMode, enabledFilters );
|
return ( UniqueEntityLoader ) loaders.get( lockMode );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -108,4 +108,12 @@ public interface Loadable extends EntityPersister {
|
||||||
|
|
||||||
public boolean isAbstract();
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,11 +19,12 @@ arbitrary number of queries, and import declarations of arbitrary classes.
|
||||||
<!ELEMENT hibernate-mapping (
|
<!ELEMENT hibernate-mapping (
|
||||||
meta*,
|
meta*,
|
||||||
typedef*,
|
typedef*,
|
||||||
import*,
|
import*,
|
||||||
(class|subclass|joined-subclass|union-subclass)*,
|
(class|subclass|joined-subclass|union-subclass)*,
|
||||||
resultset*,
|
resultset*,
|
||||||
(query|sql-query)*,
|
(query|sql-query)*,
|
||||||
filter-def*,
|
filter-def*,
|
||||||
|
fetch-profile*,
|
||||||
database-object*
|
database-object*
|
||||||
)>
|
)>
|
||||||
<!ATTLIST hibernate-mapping schema CDATA #IMPLIED> <!-- default: none -->
|
<!ATTLIST hibernate-mapping schema CDATA #IMPLIED> <!-- default: none -->
|
||||||
|
@ -78,6 +79,7 @@ arbitrary number of queries, and import declarations of arbitrary classes.
|
||||||
((join*,subclass*)|joined-subclass*|union-subclass*),
|
((join*,subclass*)|joined-subclass*|union-subclass*),
|
||||||
loader?,sql-insert?,sql-update?,sql-delete?,
|
loader?,sql-insert?,sql-update?,sql-delete?,
|
||||||
filter*,
|
filter*,
|
||||||
|
fetch-profile*,
|
||||||
resultset*,
|
resultset*,
|
||||||
(query|sql-query)*
|
(query|sql-query)*
|
||||||
)>
|
)>
|
||||||
|
@ -133,6 +135,22 @@ arbitrary number of queries, and import declarations of arbitrary classes.
|
||||||
<!ATTLIST filter name CDATA #REQUIRED>
|
<!ATTLIST filter name CDATA #REQUIRED>
|
||||||
<!ATTLIST filter condition CDATA #IMPLIED>
|
<!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 -->
|
<!-- A join allows some properties of a class to be persisted to a second table -->
|
||||||
|
|
||||||
|
@ -231,6 +249,7 @@ application through a property of the Java class. -->
|
||||||
join*,
|
join*,
|
||||||
subclass*,
|
subclass*,
|
||||||
loader?,sql-insert?,sql-update?,sql-delete?,
|
loader?,sql-insert?,sql-update?,sql-delete?,
|
||||||
|
fetch-profile*,
|
||||||
resultset*,
|
resultset*,
|
||||||
(query|sql-query)*
|
(query|sql-query)*
|
||||||
)>
|
)>
|
||||||
|
@ -263,6 +282,7 @@ application through a property of the Java class. -->
|
||||||
(property|many-to-one|one-to-one|component|dynamic-component|properties|any|map|set|list|bag|idbag|array|primitive-array)*,
|
(property|many-to-one|one-to-one|component|dynamic-component|properties|any|map|set|list|bag|idbag|array|primitive-array)*,
|
||||||
joined-subclass*,
|
joined-subclass*,
|
||||||
loader?,sql-insert?,sql-update?,sql-delete?,
|
loader?,sql-insert?,sql-update?,sql-delete?,
|
||||||
|
fetch-profile*,
|
||||||
resultset*,
|
resultset*,
|
||||||
(query|sql-query)*
|
(query|sql-query)*
|
||||||
)>
|
)>
|
||||||
|
@ -298,6 +318,7 @@ application through a property of the Java class. -->
|
||||||
(property|many-to-one|one-to-one|component|dynamic-component|properties|any|map|set|list|bag|idbag|array|primitive-array)*,
|
(property|many-to-one|one-to-one|component|dynamic-component|properties|any|map|set|list|bag|idbag|array|primitive-array)*,
|
||||||
union-subclass*,
|
union-subclass*,
|
||||||
loader?,sql-insert?,sql-update?,sql-delete?,
|
loader?,sql-insert?,sql-update?,sql-delete?,
|
||||||
|
fetch-profile*,
|
||||||
resultset*,
|
resultset*,
|
||||||
(query|sql-query)*
|
(query|sql-query)*
|
||||||
)>
|
)>
|
||||||
|
|
|
@ -198,4 +198,8 @@ public class SessionFactoryStub implements SessionFactory {
|
||||||
public FilterDefinition getFilterDefinition(String filterName) throws HibernateException {
|
public FilterDefinition getFilterDefinition(String filterName) throws HibernateException {
|
||||||
return getImpl().getFilterDefinition( filterName );
|
return getImpl().getFilterDefinition( filterName );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean containsFetchProfileDefition(String name) {
|
||||||
|
return getImpl().containsFetchProfileDefition( name );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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>
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,6 +22,7 @@ hibernate.connection.isolation ${jdbc.isolation}
|
||||||
|
|
||||||
hibernate.connection.pool_size 5
|
hibernate.connection.pool_size 5
|
||||||
|
|
||||||
|
hibernate.show_sql true
|
||||||
hibernate.format_sql true
|
hibernate.format_sql true
|
||||||
|
|
||||||
hibernate.max_fetch_depth 5
|
hibernate.max_fetch_depth 5
|
||||||
|
|
Loading…
Reference in New Issue