Save This Page
Home » spring-framework-2.5.6-with-dependencies » org.springframework » orm » hibernate3 » [javadoc | source]
    1   /*
    2    * Copyright 2002-2008 the original author or authors.
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    *      http://www.apache.org/licenses/LICENSE-2.0
    9    *
   10    * Unless required by applicable law or agreed to in writing, software
   11    * distributed under the License is distributed on an "AS IS" BASIS,
   12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   13    * See the License for the specific language governing permissions and
   14    * limitations under the License.
   15    */
   16   
   17   package org.springframework.orm.hibernate3;
   18   
   19   import java.io.Serializable;
   20   import java.lang.reflect.InvocationHandler;
   21   import java.lang.reflect.InvocationTargetException;
   22   import java.lang.reflect.Method;
   23   import java.lang.reflect.Proxy;
   24   import java.sql.SQLException;
   25   import java.util.Collection;
   26   import java.util.Iterator;
   27   import java.util.List;
   28   
   29   import org.hibernate.Criteria;
   30   import org.hibernate.Filter;
   31   import org.hibernate.FlushMode;
   32   import org.hibernate.Hibernate;
   33   import org.hibernate.HibernateException;
   34   import org.hibernate.LockMode;
   35   import org.hibernate.Query;
   36   import org.hibernate.ReplicationMode;
   37   import org.hibernate.Session;
   38   import org.hibernate.SessionFactory;
   39   import org.hibernate.criterion.DetachedCriteria;
   40   import org.hibernate.criterion.Example;
   41   import org.hibernate.engine.SessionImplementor;
   42   import org.hibernate.event.EventSource;
   43   
   44   import org.springframework.dao.DataAccessException;
   45   import org.springframework.dao.DataAccessResourceFailureException;
   46   import org.springframework.dao.InvalidDataAccessApiUsageException;
   47   import org.springframework.util.Assert;
   48   
   49   /**
   50    * Helper class that simplifies Hibernate data access code. Automatically
   51    * converts HibernateExceptions into DataAccessExceptions, following the
   52    * <code>org.springframework.dao</code> exception hierarchy.
   53    *
   54    * <p>The central method is <code>execute</code>, supporting Hibernate access code
   55    * implementing the {@link HibernateCallback} interface. It provides Hibernate Session
   56    * handling such that neither the HibernateCallback implementation nor the calling
   57    * code needs to explicitly care about retrieving/closing Hibernate Sessions,
   58    * or handling Session lifecycle exceptions. For typical single step actions,
   59    * there are various convenience methods (find, load, saveOrUpdate, delete).
   60    *
   61    * <p>Can be used within a service implementation via direct instantiation
   62    * with a SessionFactory reference, or get prepared in an application context
   63    * and given to services as bean reference. Note: The SessionFactory should
   64    * always be configured as bean in the application context, in the first case
   65    * given to the service directly, in the second case to the prepared template.
   66    *
   67    * <p><b>NOTE: As of Hibernate 3.0.1, transactional Hibernate access code can
   68    * also be coded in plain Hibernate style. Hence, for newly started projects,
   69    * consider adopting the standard Hibernate3 style of coding data access objects
   70    * instead, based on {@link org.hibernate.SessionFactory#getCurrentSession()}.</b>
   71    *
   72    * <p>This class can be considered as direct alternative to working with the raw
   73    * Hibernate3 Session API (through <code>SessionFactory.getCurrentSession()</code>).
   74    * The major advantage is its automatic conversion to DataAccessExceptions as well
   75    * as its capability to fall back to 'auto-commit' style behavior when used outside
   76    * of transactions. <b>Note that HibernateTemplate will perform its own Session
   77    * management, not participating in a custom Hibernate CurrentSessionContext
   78    * unless you explicitly switch {@link #setAllowCreate "allowCreate"} to "false".</b>
   79    *
   80    * <p>{@link LocalSessionFactoryBean} is the preferred way of obtaining a reference
   81    * to a specific Hibernate SessionFactory, at least in a non-EJB environment.
   82    * The Spring application context will manage its lifecycle, initializing and
   83    * shutting down the factory as part of the application.
   84    *
   85    * <p>Note that operations that return an Iterator (i.e. <code>iterate</code>)
   86    * are supposed to be used within Spring-driven or JTA-driven transactions
   87    * (with HibernateTransactionManager, JtaTransactionManager, or EJB CMT).
   88    * Else, the Iterator won't be able to read results from its ResultSet anymore,
   89    * as the underlying Hibernate Session will already have been closed.
   90    *
   91    * <p>Lazy loading will also just work with an open Hibernate Session,
   92    * either within a transaction or within OpenSessionInViewFilter/Interceptor.
   93    * Furthermore, some operations just make sense within transactions,
   94    * for example: <code>contains</code>, <code>evict</code>, <code>lock</code>,
   95    * <code>flush</code>, <code>clear</code>.
   96    *
   97    * @author Juergen Hoeller
   98    * @since 1.2
   99    * @see #setSessionFactory
  100    * @see HibernateCallback
  101    * @see org.hibernate.Session
  102    * @see LocalSessionFactoryBean
  103    * @see HibernateTransactionManager
  104    * @see org.springframework.transaction.jta.JtaTransactionManager
  105    * @see org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
  106    * @see org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor
  107    */
  108   public class HibernateTemplate extends HibernateAccessor implements HibernateOperations {
  109   
  110   	private boolean allowCreate = true;
  111   
  112   	private boolean alwaysUseNewSession = false;
  113   
  114   	private boolean exposeNativeSession = false;
  115   
  116   	private boolean checkWriteOperations = true;
  117   
  118   	private boolean cacheQueries = false;
  119   
  120   	private String queryCacheRegion;
  121   
  122   	private int fetchSize = 0;
  123   
  124   	private int maxResults = 0;
  125   
  126   
  127   	/**
  128   	 * Create a new HibernateTemplate instance.
  129   	 */
  130   	public HibernateTemplate() {
  131   	}
  132   
  133   	/**
  134   	 * Create a new HibernateTemplate instance.
  135   	 * @param sessionFactory SessionFactory to create Sessions
  136   	 */
  137   	public HibernateTemplate(SessionFactory sessionFactory) {
  138   		setSessionFactory(sessionFactory);
  139   		afterPropertiesSet();
  140   	}
  141   
  142   	/**
  143   	 * Create a new HibernateTemplate instance.
  144   	 * @param sessionFactory SessionFactory to create Sessions
  145   	 * @param allowCreate if a non-transactional Session should be created when no
  146   	 * transactional Session can be found for the current thread
  147   	 */
  148   	public HibernateTemplate(SessionFactory sessionFactory, boolean allowCreate) {
  149   		setSessionFactory(sessionFactory);
  150   		setAllowCreate(allowCreate);
  151   		afterPropertiesSet();
  152   	}
  153   
  154   
  155   	/**
  156   	 * Set if a new {@link Session} should be created when no transactional
  157   	 * <code>Session</code> can be found for the current thread.
  158   	 * The default value is <code>true</code>.
  159   	 * <p><code>HibernateTemplate</code> is aware of a corresponding
  160   	 * <code>Session</code> bound to the current thread, for example when using
  161   	 * {@link HibernateTransactionManager}. If <code>allowCreate</code> is
  162   	 * <code>true</code>, a new non-transactional <code>Session</code> will be
  163   	 * created if none is found, which needs to be closed at the end of the operation.
  164   	 * If <code>false</code>, an {@link IllegalStateException} will get thrown in
  165   	 * this case.
  166   	 * <p><b>NOTE: As of Spring 2.5, switching <code>allowCreate</code>
  167   	 * to <code>false</code> will delegate to Hibernate's
  168   	 * {@link org.hibernate.SessionFactory#getCurrentSession()} method,</b>
  169   	 * which - with Spring-based setup - will by default delegate to Spring's
  170   	 * <code>SessionFactoryUtils.getSession(sessionFactory, false)</code>.
  171   	 * This mode also allows for custom Hibernate CurrentSessionContext strategies
  172   	 * to be plugged in, whereas <code>allowCreate</code> set to <code>true</code>
  173   	 * will always use a Spring-managed Hibernate Session.
  174   	 * @see SessionFactoryUtils#getSession(SessionFactory, boolean)
  175   	 */
  176   	public void setAllowCreate(boolean allowCreate) {
  177   		this.allowCreate = allowCreate;
  178   	}
  179   
  180   	/**
  181   	 * Return if a new Session should be created if no thread-bound found.
  182   	 */
  183   	public boolean isAllowCreate() {
  184   		return this.allowCreate;
  185   	}
  186   
  187   	/**
  188   	 * Set whether to always use a new Hibernate Session for this template.
  189   	 * Default is "false"; if activated, all operations on this template will
  190   	 * work on a new Hibernate Session even in case of a pre-bound Session
  191   	 * (for example, within a transaction or OpenSessionInViewFilter).
  192   	 * <p>Within a transaction, a new Hibernate Session used by this template
  193   	 * will participate in the transaction through using the same JDBC
  194   	 * Connection. In such a scenario, multiple Sessions will participate
  195   	 * in the same database transaction.
  196   	 * <p>Turn this on for operations that are supposed to always execute
  197   	 * independently, without side effects caused by a shared Hibernate Session.
  198   	 */
  199   	public void setAlwaysUseNewSession(boolean alwaysUseNewSession) {
  200   		this.alwaysUseNewSession = alwaysUseNewSession;
  201   	}
  202   
  203   	/**
  204   	 * Return whether to always use a new Hibernate Session for this template.
  205   	 */
  206   	public boolean isAlwaysUseNewSession() {
  207   		return this.alwaysUseNewSession;
  208   	}
  209   
  210   	/**
  211   	 * Set whether to expose the native Hibernate Session to
  212   	 * HibernateCallback code.
  213   	 * <p>Default is "false": a Session proxy will be returned, suppressing
  214   	 * <code>close</code> calls and automatically applying query cache
  215   	 * settings and transaction timeouts.
  216   	 * @see HibernateCallback
  217   	 * @see org.hibernate.Session
  218   	 * @see #setCacheQueries
  219   	 * @see #setQueryCacheRegion
  220   	 * @see #prepareQuery
  221   	 * @see #prepareCriteria
  222   	 */
  223   	public void setExposeNativeSession(boolean exposeNativeSession) {
  224   		this.exposeNativeSession = exposeNativeSession;
  225   	}
  226   
  227   	/**
  228   	 * Return whether to expose the native Hibernate Session to
  229   	 * HibernateCallback code, or rather a Session proxy.
  230   	 */
  231   	public boolean isExposeNativeSession() {
  232   		return this.exposeNativeSession;
  233   	}
  234   
  235   	/**
  236   	 * Set whether to check that the Hibernate Session is not in read-only mode
  237   	 * in case of write operations (save/update/delete).
  238   	 * <p>Default is "true", for fail-fast behavior when attempting write operations
  239   	 * within a read-only transaction. Turn this off to allow save/update/delete
  240   	 * on a Session with flush mode NEVER.
  241   	 * @see #setFlushMode
  242   	 * @see #checkWriteOperationAllowed
  243   	 * @see org.springframework.transaction.TransactionDefinition#isReadOnly
  244   	 */
  245   	public void setCheckWriteOperations(boolean checkWriteOperations) {
  246   		this.checkWriteOperations = checkWriteOperations;
  247   	}
  248   
  249   	/**
  250   	 * Return whether to check that the Hibernate Session is not in read-only
  251   	 * mode in case of write operations (save/update/delete).
  252   	 */
  253   	public boolean isCheckWriteOperations() {
  254   		return this.checkWriteOperations;
  255   	}
  256   
  257   	/**
  258   	 * Set whether to cache all queries executed by this template.
  259   	 * <p>If this is "true", all Query and Criteria objects created by
  260   	 * this template will be marked as cacheable (including all
  261   	 * queries through find methods).
  262   	 * <p>To specify the query region to be used for queries cached
  263   	 * by this template, set the "queryCacheRegion" property.
  264   	 * @see #setQueryCacheRegion
  265   	 * @see org.hibernate.Query#setCacheable
  266   	 * @see org.hibernate.Criteria#setCacheable
  267   	 */
  268   	public void setCacheQueries(boolean cacheQueries) {
  269   		this.cacheQueries = cacheQueries;
  270   	}
  271   
  272   	/**
  273   	 * Return whether to cache all queries executed by this template.
  274   	 */
  275   	public boolean isCacheQueries() {
  276   		return this.cacheQueries;
  277   	}
  278   
  279   	/**
  280   	 * Set the name of the cache region for queries executed by this template.
  281   	 * <p>If this is specified, it will be applied to all Query and Criteria objects
  282   	 * created by this template (including all queries through find methods).
  283   	 * <p>The cache region will not take effect unless queries created by this
  284   	 * template are configured to be cached via the "cacheQueries" property.
  285   	 * @see #setCacheQueries
  286   	 * @see org.hibernate.Query#setCacheRegion
  287   	 * @see org.hibernate.Criteria#setCacheRegion
  288   	 */
  289   	public void setQueryCacheRegion(String queryCacheRegion) {
  290   		this.queryCacheRegion = queryCacheRegion;
  291   	}
  292   
  293   	/**
  294   	 * Return the name of the cache region for queries executed by this template.
  295   	 */
  296   	public String getQueryCacheRegion() {
  297   		return this.queryCacheRegion;
  298   	}
  299   
  300   	/**
  301   	 * Set the fetch size for this HibernateTemplate. This is important for processing
  302   	 * large result sets: Setting this higher than the default value will increase
  303   	 * processing speed at the cost of memory consumption; setting this lower can
  304   	 * avoid transferring row data that will never be read by the application.
  305   	 * <p>Default is 0, indicating to use the JDBC driver's default.
  306   	 */
  307   	public void setFetchSize(int fetchSize) {
  308   		this.fetchSize = fetchSize;
  309   	}
  310   
  311   	/**
  312   	 * Return the fetch size specified for this HibernateTemplate.
  313   	 */
  314   	public int getFetchSize() {
  315   		return this.fetchSize;
  316   	}
  317   
  318   	/**
  319   	 * Set the maximum number of rows for this HibernateTemplate. This is important
  320   	 * for processing subsets of large result sets, avoiding to read and hold
  321   	 * the entire result set in the database or in the JDBC driver if we're
  322   	 * never interested in the entire result in the first place (for example,
  323   	 * when performing searches that might return a large number of matches).
  324   	 * <p>Default is 0, indicating to use the JDBC driver's default.
  325   	 */
  326   	public void setMaxResults(int maxResults) {
  327   		this.maxResults = maxResults;
  328   	}
  329   
  330   	/**
  331   	 * Return the maximum number of rows specified for this HibernateTemplate.
  332   	 */
  333   	public int getMaxResults() {
  334   		return this.maxResults;
  335   	}
  336   
  337   
  338   	public Object execute(HibernateCallback action) throws DataAccessException {
  339   		return doExecute(action, false, false);
  340   	}
  341   
  342   	public List executeFind(HibernateCallback action) throws DataAccessException {
  343   		Object result = doExecute(action, false, false);
  344   		if (result != null && !(result instanceof List)) {
  345   			throw new InvalidDataAccessApiUsageException(
  346   					"Result object returned from HibernateCallback isn't a List: [" + result + "]");
  347   		}
  348   		return (List) result;
  349   	}
  350   
  351   	/**
  352   	 * Execute the action specified by the given action object within a
  353   	 * new {@link org.hibernate.Session}.
  354   	 * <p>This execute variant overrides the template-wide
  355   	 * {@link #isAlwaysUseNewSession() "alwaysUseNewSession"} setting.
  356   	 * @param action callback object that specifies the Hibernate action
  357   	 * @return a result object returned by the action, or <code>null</code>
  358   	 * @throws org.springframework.dao.DataAccessException in case of Hibernate errors
  359   	 */
  360   	public Object executeWithNewSession(HibernateCallback action) {
  361   		return doExecute(action, true, false);
  362   	}
  363   
  364   	/**
  365   	 * Execute the action specified by the given action object within a
  366   	 * native {@link org.hibernate.Session}.
  367   	 * <p>This execute variant overrides the template-wide
  368   	 * {@link #isExposeNativeSession() "exposeNativeSession"} setting.
  369   	 * @param action callback object that specifies the Hibernate action
  370   	 * @return a result object returned by the action, or <code>null</code>
  371   	 * @throws org.springframework.dao.DataAccessException in case of Hibernate errors
  372   	 */
  373   	public Object executeWithNativeSession(HibernateCallback action) {
  374   		return doExecute(action, false, true);
  375   	}
  376   
  377   	/**
  378   	 * Execute the action specified by the given action object within a Session.
  379   	 * @param action callback object that specifies the Hibernate action
  380   	 * @param enforceNativeSession whether to enforce exposure of the native
  381   	 * Hibernate Session to callback code
  382   	 * @return a result object returned by the action, or <code>null</code>
  383   	 * @throws org.springframework.dao.DataAccessException in case of Hibernate errors
  384   	 * @deprecated as of Spring 2.5, in favor of {@link #executeWithNativeSession}
  385   	 */
  386   	public Object execute(HibernateCallback action, boolean enforceNativeSession) throws DataAccessException {
  387   		return doExecute(action, false, enforceNativeSession);
  388   	}
  389   
  390   	/**
  391   	 * Execute the action specified by the given action object within a Session.
  392   	 * @param action callback object that specifies the Hibernate action
  393   	 * @param enforceNewSession whether to enforce a new Session for this template
  394   	 * even if there is a pre-bound transactional Session
  395   	 * @param enforceNativeSession whether to enforce exposure of the native
  396   	 * Hibernate Session to callback code
  397   	 * @return a result object returned by the action, or <code>null</code>
  398   	 * @throws org.springframework.dao.DataAccessException in case of Hibernate errors
  399   	 */
  400   	protected Object doExecute(HibernateCallback action, boolean enforceNewSession, boolean enforceNativeSession)
  401   			throws DataAccessException {
  402   
  403   		Assert.notNull(action, "Callback object must not be null");
  404   
  405   		Session session = (enforceNewSession ?
  406   				SessionFactoryUtils.getNewSession(getSessionFactory(), getEntityInterceptor()) : getSession());
  407   		boolean existingTransaction = (!enforceNewSession &&
  408   				(!isAllowCreate() || SessionFactoryUtils.isSessionTransactional(session, getSessionFactory())));
  409   		if (existingTransaction) {
  410   			logger.debug("Found thread-bound Session for HibernateTemplate");
  411   		}
  412   
  413   		FlushMode previousFlushMode = null;
  414   		try {
  415   			previousFlushMode = applyFlushMode(session, existingTransaction);
  416   			enableFilters(session);
  417   			Session sessionToExpose =
  418   					(enforceNativeSession || isExposeNativeSession() ? session : createSessionProxy(session));
  419   			Object result = action.doInHibernate(sessionToExpose);
  420   			flushIfNecessary(session, existingTransaction);
  421   			return result;
  422   		}
  423   		catch (HibernateException ex) {
  424   			throw convertHibernateAccessException(ex);
  425   		}
  426   		catch (SQLException ex) {
  427   			throw convertJdbcAccessException(ex);
  428   		}
  429   		catch (RuntimeException ex) {
  430   			// Callback code threw application exception...
  431   			throw ex;
  432   		}
  433   		finally {
  434   			if (existingTransaction) {
  435   				logger.debug("Not closing pre-bound Hibernate Session after HibernateTemplate");
  436   				disableFilters(session);
  437   				if (previousFlushMode != null) {
  438   					session.setFlushMode(previousFlushMode);
  439   				}
  440   			}
  441   			else {
  442   				// Never use deferred close for an explicitly new Session.
  443   				if (isAlwaysUseNewSession()) {
  444   					SessionFactoryUtils.closeSession(session);
  445   				}
  446   				else {
  447   					SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, getSessionFactory());
  448   				}
  449   			}
  450   		}
  451   	}
  452   
  453   	/**
  454   	 * Return a Session for use by this template.
  455   	 * <p>Returns a new Session in case of "alwaysUseNewSession" (using the same
  456   	 * JDBC Connection as a transactional Session, if applicable), a pre-bound
  457   	 * Session in case of "allowCreate" turned off, and a pre-bound or new Session
  458   	 * otherwise (new only if no transactional or otherwise pre-bound Session exists).
  459   	 * @return the Session to use (never <code>null</code>)
  460   	 * @see SessionFactoryUtils#getSession
  461   	 * @see SessionFactoryUtils#getNewSession
  462   	 * @see #setAlwaysUseNewSession
  463   	 * @see #setAllowCreate
  464   	 */
  465   	protected Session getSession() {
  466   		if (isAlwaysUseNewSession()) {
  467   			return SessionFactoryUtils.getNewSession(getSessionFactory(), getEntityInterceptor());
  468   		}
  469   		else if (isAllowCreate()) {
  470   			return SessionFactoryUtils.getSession(
  471   					getSessionFactory(), getEntityInterceptor(), getJdbcExceptionTranslator());
  472   		}
  473   		else if (SessionFactoryUtils.hasTransactionalSession(getSessionFactory())) {
  474   			return SessionFactoryUtils.getSession(getSessionFactory(), false);
  475   		}
  476   		else {
  477   			try {
  478   				return getSessionFactory().getCurrentSession();
  479   			}
  480   			catch (HibernateException ex) {
  481   				throw new DataAccessResourceFailureException("Could not obtain current Hibernate Session", ex);
  482   			}
  483   		}
  484   	}
  485   
  486   	/**
  487   	 * Create a close-suppressing proxy for the given Hibernate Session.
  488   	 * The proxy also prepares returned Query and Criteria objects.
  489   	 * @param session the Hibernate Session to create a proxy for
  490   	 * @return the Session proxy
  491   	 * @see org.hibernate.Session#close()
  492   	 * @see #prepareQuery
  493   	 * @see #prepareCriteria
  494   	 */
  495   	protected Session createSessionProxy(Session session) {
  496   		Class[] sessionIfcs = null;
  497   		Class mainIfc = (session instanceof org.hibernate.classic.Session ?
  498   				org.hibernate.classic.Session.class : Session.class);
  499   		if (session instanceof EventSource) {
  500   			sessionIfcs = new Class[] {mainIfc, EventSource.class};
  501   		}
  502   		else if (session instanceof SessionImplementor) {
  503   			sessionIfcs = new Class[] {mainIfc, SessionImplementor.class};
  504   		}
  505   		else {
  506   			sessionIfcs = new Class[] {mainIfc};
  507   		}
  508   		return (Session) Proxy.newProxyInstance(
  509   				session.getClass().getClassLoader(), sessionIfcs,
  510   				new CloseSuppressingInvocationHandler(session));
  511   	}
  512   
  513   
  514   	//-------------------------------------------------------------------------
  515   	// Convenience methods for loading individual objects
  516   	//-------------------------------------------------------------------------
  517   
  518   	public Object get(Class entityClass, Serializable id) throws DataAccessException {
  519   		return get(entityClass, id, null);
  520   	}
  521   
  522   	public Object get(final Class entityClass, final Serializable id, final LockMode lockMode)
  523   			throws DataAccessException {
  524   
  525   		return executeWithNativeSession(new HibernateCallback() {
  526   			public Object doInHibernate(Session session) throws HibernateException {
  527   				if (lockMode != null) {
  528   					return session.get(entityClass, id, lockMode);
  529   				}
  530   				else {
  531   					return session.get(entityClass, id);
  532   				}
  533   			}
  534   		});
  535   	}
  536   
  537   	public Object get(String entityName, Serializable id) throws DataAccessException {
  538   		return get(entityName, id, null);
  539   	}
  540   
  541   	public Object get(final String entityName, final Serializable id, final LockMode lockMode)
  542   			throws DataAccessException {
  543   
  544   		return executeWithNativeSession(new HibernateCallback() {
  545   			public Object doInHibernate(Session session) throws HibernateException {
  546   				if (lockMode != null) {
  547   					return session.get(entityName, id, lockMode);
  548   				}
  549   				else {
  550   					return session.get(entityName, id);
  551   				}
  552   			}
  553   		});
  554   	}
  555   
  556   	public Object load(Class entityClass, Serializable id) throws DataAccessException {
  557   		return load(entityClass, id, null);
  558   	}
  559   
  560   	public Object load(final Class entityClass, final Serializable id, final LockMode lockMode)
  561   			throws DataAccessException {
  562   
  563   		return executeWithNativeSession(new HibernateCallback() {
  564   			public Object doInHibernate(Session session) throws HibernateException {
  565   				if (lockMode != null) {
  566   					return session.load(entityClass, id, lockMode);
  567   				}
  568   				else {
  569   					return session.load(entityClass, id);
  570   				}
  571   			}
  572   		});
  573   	}
  574   
  575   	public Object load(String entityName, Serializable id) throws DataAccessException {
  576   		return load(entityName, id, null);
  577   	}
  578   
  579   	public Object load(final String entityName, final Serializable id, final LockMode lockMode)
  580   			throws DataAccessException {
  581   
  582   		return executeWithNativeSession(new HibernateCallback() {
  583   			public Object doInHibernate(Session session) throws HibernateException {
  584   				if (lockMode != null) {
  585   					return session.load(entityName, id, lockMode);
  586   				}
  587   				else {
  588   					return session.load(entityName, id);
  589   				}
  590   			}
  591   		});
  592   	}
  593   
  594   	public List loadAll(final Class entityClass) throws DataAccessException {
  595   		return (List) executeWithNativeSession(new HibernateCallback() {
  596   			public Object doInHibernate(Session session) throws HibernateException {
  597   				Criteria criteria = session.createCriteria(entityClass);
  598   				criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
  599   				prepareCriteria(criteria);
  600   				return criteria.list();
  601   			}
  602   		});
  603   	}
  604   
  605   	public void load(final Object entity, final Serializable id) throws DataAccessException {
  606   		executeWithNativeSession(new HibernateCallback() {
  607   			public Object doInHibernate(Session session) throws HibernateException {
  608   				session.load(entity, id);
  609   				return null;
  610   			}
  611   		});
  612   	}
  613   
  614   	public void refresh(final Object entity) throws DataAccessException {
  615   		refresh(entity, null);
  616   	}
  617   
  618   	public void refresh(final Object entity, final LockMode lockMode) throws DataAccessException {
  619   		executeWithNativeSession(new HibernateCallback() {
  620   			public Object doInHibernate(Session session) throws HibernateException {
  621   				if (lockMode != null) {
  622   					session.refresh(entity, lockMode);
  623   				}
  624   				else {
  625   					session.refresh(entity);
  626   				}
  627   				return null;
  628   			}
  629   		});
  630   	}
  631   
  632   	public boolean contains(final Object entity) throws DataAccessException {
  633   		Boolean result = (Boolean) executeWithNativeSession(new HibernateCallback() {
  634   			public Object doInHibernate(Session session) {
  635   				return (session.contains(entity) ? Boolean.TRUE : Boolean.FALSE);
  636   			}
  637   		});
  638   		return result.booleanValue();
  639   	}
  640   
  641   	public void evict(final Object entity) throws DataAccessException {
  642   		executeWithNativeSession(new HibernateCallback() {
  643   			public Object doInHibernate(Session session) throws HibernateException {
  644   				session.evict(entity);
  645   				return null;
  646   			}
  647   		});
  648   	}
  649   
  650   	public void initialize(Object proxy) throws DataAccessException {
  651   		try {
  652   			Hibernate.initialize(proxy);
  653   		}
  654   		catch (HibernateException ex) {
  655   			throw SessionFactoryUtils.convertHibernateAccessException(ex);
  656   		}
  657   	}
  658   
  659   	public Filter enableFilter(String filterName) throws IllegalStateException {
  660   		Session session = SessionFactoryUtils.getSession(getSessionFactory(), false);
  661   		Filter filter = session.getEnabledFilter(filterName);
  662   		if (filter == null) {
  663   			filter = session.enableFilter(filterName);
  664   		}
  665   		return filter;
  666   	}
  667   
  668   
  669   	//-------------------------------------------------------------------------
  670   	// Convenience methods for storing individual objects
  671   	//-------------------------------------------------------------------------
  672   
  673   	public void lock(final Object entity, final LockMode lockMode) throws DataAccessException {
  674   		executeWithNativeSession(new HibernateCallback() {
  675   			public Object doInHibernate(Session session) throws HibernateException {
  676   				session.lock(entity, lockMode);
  677   				return null;
  678   			}
  679   		});
  680   	}
  681   
  682   	public void lock(final String entityName, final Object entity, final LockMode lockMode)
  683   			throws DataAccessException {
  684   
  685   		executeWithNativeSession(new HibernateCallback() {
  686   			public Object doInHibernate(Session session) throws HibernateException {
  687   				session.lock(entityName, entity, lockMode);
  688   				return null;
  689   			}
  690   		});
  691   	}
  692   
  693   	public Serializable save(final Object entity) throws DataAccessException {
  694   		return (Serializable) executeWithNativeSession(new HibernateCallback() {
  695   			public Object doInHibernate(Session session) throws HibernateException {
  696   				checkWriteOperationAllowed(session);
  697   				return session.save(entity);
  698   			}
  699   		});
  700   	}
  701   
  702   	public Serializable save(final String entityName, final Object entity) throws DataAccessException {
  703   		return (Serializable) executeWithNativeSession(new HibernateCallback() {
  704   			public Object doInHibernate(Session session) throws HibernateException {
  705   				checkWriteOperationAllowed(session);
  706   				return session.save(entityName, entity);
  707   			}
  708   		});
  709   	}
  710   
  711   	public void update(Object entity) throws DataAccessException {
  712   		update(entity, null);
  713   	}
  714   
  715   	public void update(final Object entity, final LockMode lockMode) throws DataAccessException {
  716   		executeWithNativeSession(new HibernateCallback() {
  717   			public Object doInHibernate(Session session) throws HibernateException {
  718   				checkWriteOperationAllowed(session);
  719   				session.update(entity);
  720   				if (lockMode != null) {
  721   					session.lock(entity, lockMode);
  722   				}
  723   				return null;
  724   			}
  725   		});
  726   	}
  727   
  728   	public void update(String entityName, Object entity) throws DataAccessException {
  729   		update(entityName, entity, null);
  730   	}
  731   
  732   	public void update(final String entityName, final Object entity, final LockMode lockMode)
  733   			throws DataAccessException {
  734   
  735   		executeWithNativeSession(new HibernateCallback() {
  736   			public Object doInHibernate(Session session) throws HibernateException {
  737   				checkWriteOperationAllowed(session);
  738   				session.update(entityName, entity);
  739   				if (lockMode != null) {
  740   					session.lock(entity, lockMode);
  741   				}
  742   				return null;
  743   			}
  744   		});
  745   	}
  746   
  747   	public void saveOrUpdate(final Object entity) throws DataAccessException {
  748   		executeWithNativeSession(new HibernateCallback() {
  749   			public Object doInHibernate(Session session) throws HibernateException {
  750   				checkWriteOperationAllowed(session);
  751   				session.saveOrUpdate(entity);
  752   				return null;
  753   			}
  754   		});
  755   	}
  756   
  757   	public void saveOrUpdate(final String entityName, final Object entity) throws DataAccessException {
  758   		executeWithNativeSession(new HibernateCallback() {
  759   			public Object doInHibernate(Session session) throws HibernateException {
  760   				checkWriteOperationAllowed(session);
  761   				session.saveOrUpdate(entityName, entity);
  762   				return null;
  763   			}
  764   		});
  765   	}
  766   
  767   	public void saveOrUpdateAll(final Collection entities) throws DataAccessException {
  768   		executeWithNativeSession(new HibernateCallback() {
  769   			public Object doInHibernate(Session session) throws HibernateException {
  770   				checkWriteOperationAllowed(session);
  771   				for (Iterator it = entities.iterator(); it.hasNext();) {
  772   					session.saveOrUpdate(it.next());
  773   				}
  774   				return null;
  775   			}
  776   		});
  777   	}
  778   
  779   	public void replicate(final Object entity, final ReplicationMode replicationMode)
  780   			throws DataAccessException {
  781   
  782   		executeWithNativeSession(new HibernateCallback() {
  783   			public Object doInHibernate(Session session) throws HibernateException {
  784   				checkWriteOperationAllowed(session);
  785   				session.replicate(entity, replicationMode);
  786   				return null;
  787   			}
  788   		});
  789   	}
  790   
  791   	public void replicate(final String entityName, final Object entity, final ReplicationMode replicationMode)
  792   			throws DataAccessException {
  793   
  794   		executeWithNativeSession(new HibernateCallback() {
  795   			public Object doInHibernate(Session session) throws HibernateException {
  796   				checkWriteOperationAllowed(session);
  797   				session.replicate(entityName, entity, replicationMode);
  798   				return null;
  799   			}
  800   		});
  801   	}
  802   
  803   	public void persist(final Object entity) throws DataAccessException {
  804   		executeWithNativeSession(new HibernateCallback() {
  805   			public Object doInHibernate(Session session) throws HibernateException {
  806   				checkWriteOperationAllowed(session);
  807   				session.persist(entity);
  808   				return null;
  809   			}
  810   		});
  811   	}
  812   
  813   	public void persist(final String entityName, final Object entity) throws DataAccessException {
  814   		executeWithNativeSession(new HibernateCallback() {
  815   			public Object doInHibernate(Session session) throws HibernateException {
  816   				checkWriteOperationAllowed(session);
  817   				session.persist(entityName, entity);
  818   				return null;
  819   			}
  820   		});
  821   	}
  822   
  823   	public Object merge(final Object entity) throws DataAccessException {
  824   		return executeWithNativeSession(new HibernateCallback() {
  825   			public Object doInHibernate(Session session) throws HibernateException {
  826   				checkWriteOperationAllowed(session);
  827   				return session.merge(entity);
  828   			}
  829   		});
  830   	}
  831   
  832   	public Object merge(final String entityName, final Object entity) throws DataAccessException {
  833   		return executeWithNativeSession(new HibernateCallback() {
  834   			public Object doInHibernate(Session session) throws HibernateException {
  835   				checkWriteOperationAllowed(session);
  836   				return session.merge(entityName, entity);
  837   			}
  838   		});
  839   	}
  840   
  841   	public void delete(Object entity) throws DataAccessException {
  842   		delete(entity, null);
  843   	}
  844   
  845   	public void delete(final Object entity, final LockMode lockMode) throws DataAccessException {
  846   		executeWithNativeSession(new HibernateCallback() {
  847   			public Object doInHibernate(Session session) throws HibernateException {
  848   				checkWriteOperationAllowed(session);
  849   				if (lockMode != null) {
  850   					session.lock(entity, lockMode);
  851   				}
  852   				session.delete(entity);
  853   				return null;
  854   			}
  855   		});
  856   	}
  857   
  858   	public void delete(String entityName, Object entity) throws DataAccessException {
  859   		delete(entityName, entity, null);
  860   	}
  861   
  862   	public void delete(final String entityName, final Object entity, final LockMode lockMode)
  863   			throws DataAccessException {
  864   
  865   		executeWithNativeSession(new HibernateCallback() {
  866   			public Object doInHibernate(Session session) throws HibernateException {
  867   				checkWriteOperationAllowed(session);
  868   				if (lockMode != null) {
  869   					session.lock(entityName, entity, lockMode);
  870   				}
  871   				session.delete(entityName, entity);
  872   				return null;
  873   			}
  874   		});
  875   	}
  876   
  877   	public void deleteAll(final Collection entities) throws DataAccessException {
  878   		executeWithNativeSession(new HibernateCallback() {
  879   			public Object doInHibernate(Session session) throws HibernateException {
  880   				checkWriteOperationAllowed(session);
  881   				for (Iterator it = entities.iterator(); it.hasNext();) {
  882   					session.delete(it.next());
  883   				}
  884   				return null;
  885   			}
  886   		});
  887   	}
  888   
  889   	public void flush() throws DataAccessException {
  890   		executeWithNativeSession(new HibernateCallback() {
  891   			public Object doInHibernate(Session session) throws HibernateException {
  892   				session.flush();
  893   				return null;
  894   			}
  895   		});
  896   	}
  897   
  898   	public void clear() throws DataAccessException {
  899   		executeWithNativeSession(new HibernateCallback() {
  900   			public Object doInHibernate(Session session) {
  901   				session.clear();
  902   				return null;
  903   			}
  904   		});
  905   	}
  906   
  907   
  908   	//-------------------------------------------------------------------------
  909   	// Convenience finder methods for HQL strings
  910   	//-------------------------------------------------------------------------
  911   
  912   	public List find(String queryString) throws DataAccessException {
  913   		return find(queryString, (Object[]) null);
  914   	}
  915   
  916   	public List find(String queryString, Object value) throws DataAccessException {
  917   		return find(queryString, new Object[] {value});
  918   	}
  919   
  920   	public List find(final String queryString, final Object[] values) throws DataAccessException {
  921   		return (List) executeWithNativeSession(new HibernateCallback() {
  922   			public Object doInHibernate(Session session) throws HibernateException {
  923   				Query queryObject = session.createQuery(queryString);
  924   				prepareQuery(queryObject);
  925   				if (values != null) {
  926   					for (int i = 0; i < values.length; i++) {
  927   						queryObject.setParameter(i, values[i]);
  928   					}
  929   				}
  930   				return queryObject.list();
  931   			}
  932   		});
  933   	}
  934   
  935   	public List findByNamedParam(String queryString, String paramName, Object value)
  936   			throws DataAccessException {
  937   
  938   		return findByNamedParam(queryString, new String[] {paramName}, new Object[] {value});
  939   	}
  940   
  941   	public List findByNamedParam(final String queryString, final String[] paramNames, final Object[] values)
  942   			throws DataAccessException {
  943   
  944   		if (paramNames.length != values.length) {
  945   			throw new IllegalArgumentException("Length of paramNames array must match length of values array");
  946   		}
  947   		return (List) executeWithNativeSession(new HibernateCallback() {
  948   			public Object doInHibernate(Session session) throws HibernateException {
  949   				Query queryObject = session.createQuery(queryString);
  950   				prepareQuery(queryObject);
  951   				if (values != null) {
  952   					for (int i = 0; i < values.length; i++) {
  953   						applyNamedParameterToQuery(queryObject, paramNames[i], values[i]);
  954   					}
  955   				}
  956   				return queryObject.list();
  957   			}
  958   		});
  959   	}
  960   
  961   	public List findByValueBean(final String queryString, final Object valueBean)
  962   			throws DataAccessException {
  963   
  964   		return (List) executeWithNativeSession(new HibernateCallback() {
  965   			public Object doInHibernate(Session session) throws HibernateException {
  966   				Query queryObject = session.createQuery(queryString);
  967   				prepareQuery(queryObject);
  968   				queryObject.setProperties(valueBean);
  969   				return queryObject.list();
  970   			}
  971   		});
  972   	}
  973   
  974   
  975   	//-------------------------------------------------------------------------
  976   	// Convenience finder methods for named queries
  977   	//-------------------------------------------------------------------------
  978   
  979   	public List findByNamedQuery(String queryName) throws DataAccessException {
  980   		return findByNamedQuery(queryName, (Object[]) null);
  981   	}
  982   
  983   	public List findByNamedQuery(String queryName, Object value) throws DataAccessException {
  984   		return findByNamedQuery(queryName, new Object[] {value});
  985   	}
  986   
  987   	public List findByNamedQuery(final String queryName, final Object[] values) throws DataAccessException {
  988   		return (List) executeWithNativeSession(new HibernateCallback() {
  989   			public Object doInHibernate(Session session) throws HibernateException {
  990   				Query queryObject = session.getNamedQuery(queryName);
  991   				prepareQuery(queryObject);
  992   				if (values != null) {
  993   					for (int i = 0; i < values.length; i++) {
  994   						queryObject.setParameter(i, values[i]);
  995   					}
  996   				}
  997   				return queryObject.list();
  998   			}
  999   		});
 1000   	}
 1001   
 1002   	public List findByNamedQueryAndNamedParam(String queryName, String paramName, Object value)
 1003   			throws DataAccessException {
 1004   
 1005   		return findByNamedQueryAndNamedParam(queryName, new String[] {paramName}, new Object[] {value});
 1006   	}
 1007   
 1008   	public List findByNamedQueryAndNamedParam(
 1009   			final String queryName, final String[] paramNames, final Object[] values)
 1010   			throws DataAccessException {
 1011   
 1012   		if (paramNames != null && values != null && paramNames.length != values.length) {
 1013   			throw new IllegalArgumentException("Length of paramNames array must match length of values array");
 1014   		}
 1015   		return (List) executeWithNativeSession(new HibernateCallback() {
 1016   			public Object doInHibernate(Session session) throws HibernateException {
 1017   				Query queryObject = session.getNamedQuery(queryName);
 1018   				prepareQuery(queryObject);
 1019   				if (values != null) {
 1020   					for (int i = 0; i < values.length; i++) {
 1021   						applyNamedParameterToQuery(queryObject, paramNames[i], values[i]);
 1022   					}
 1023   				}
 1024   				return queryObject.list();
 1025   			}
 1026   		});
 1027   	}
 1028   
 1029   	public List findByNamedQueryAndValueBean(final String queryName, final Object valueBean)
 1030   			throws DataAccessException {
 1031   
 1032   		return (List) executeWithNativeSession(new HibernateCallback() {
 1033   			public Object doInHibernate(Session session) throws HibernateException {
 1034   				Query queryObject = session.getNamedQuery(queryName);
 1035   				prepareQuery(queryObject);
 1036   				queryObject.setProperties(valueBean);
 1037   				return queryObject.list();
 1038   			}
 1039   		});
 1040   	}
 1041   
 1042   
 1043   	//-------------------------------------------------------------------------
 1044   	// Convenience finder methods for detached criteria
 1045   	//-------------------------------------------------------------------------
 1046   
 1047   	public List findByCriteria(DetachedCriteria criteria) throws DataAccessException {
 1048   		return findByCriteria(criteria, -1, -1);
 1049   	}
 1050   
 1051   	public List findByCriteria(final DetachedCriteria criteria, final int firstResult, final int maxResults)
 1052   			throws DataAccessException {
 1053   
 1054   		Assert.notNull(criteria, "DetachedCriteria must not be null");
 1055   		return (List) executeWithNativeSession(new HibernateCallback() {
 1056   			public Object doInHibernate(Session session) throws HibernateException {
 1057   				Criteria executableCriteria = criteria.getExecutableCriteria(session);
 1058   				prepareCriteria(executableCriteria);
 1059   				if (firstResult >= 0) {
 1060   					executableCriteria.setFirstResult(firstResult);
 1061   				}
 1062   				if (maxResults > 0) {
 1063   					executableCriteria.setMaxResults(maxResults);
 1064   				}
 1065   				return executableCriteria.list();
 1066   			}
 1067   		});
 1068   	}
 1069   
 1070   	public List findByExample(Object exampleEntity) throws DataAccessException {
 1071   		return findByExample(null, exampleEntity, -1, -1);
 1072   	}
 1073   
 1074   	public List findByExample(String entityName, Object exampleEntity) throws DataAccessException {
 1075   		return findByExample(entityName, exampleEntity, -1, -1);
 1076   	}
 1077   
 1078   	public List findByExample(Object exampleEntity, int firstResult, int maxResults) throws DataAccessException {
 1079   		return findByExample(null, exampleEntity, firstResult, maxResults);
 1080   	}
 1081   
 1082   	public List findByExample(
 1083   			final String entityName, final Object exampleEntity, final int firstResult, final int maxResults)
 1084   			throws DataAccessException {
 1085   
 1086   		Assert.notNull(exampleEntity, "Example entity must not be null");
 1087   		return (List) executeWithNativeSession(new HibernateCallback() {
 1088   			public Object doInHibernate(Session session) throws HibernateException {
 1089   				Criteria executableCriteria = (entityName != null ?
 1090   						session.createCriteria(entityName) : session.createCriteria(exampleEntity.getClass()));
 1091   				executableCriteria.add(Example.create(exampleEntity));
 1092   				prepareCriteria(executableCriteria);
 1093   				if (firstResult >= 0) {
 1094   					executableCriteria.setFirstResult(firstResult);
 1095   				}
 1096   				if (maxResults > 0) {
 1097   					executableCriteria.setMaxResults(maxResults);
 1098   				}
 1099   				return executableCriteria.list();
 1100   			}
 1101   		});
 1102   	}
 1103   
 1104   
 1105   	//-------------------------------------------------------------------------
 1106   	// Convenience query methods for iteration and bulk updates/deletes
 1107   	//-------------------------------------------------------------------------
 1108   
 1109   	public Iterator iterate(String queryString) throws DataAccessException {
 1110   		return iterate(queryString, (Object[]) null);
 1111   	}
 1112   
 1113   	public Iterator iterate(String queryString, Object value) throws DataAccessException {
 1114   		return iterate(queryString, new Object[] {value});
 1115   	}
 1116   
 1117   	public Iterator iterate(final String queryString, final Object[] values) throws DataAccessException {
 1118   		return (Iterator) executeWithNativeSession(new HibernateCallback() {
 1119   			public Object doInHibernate(Session session) throws HibernateException {
 1120   				Query queryObject = session.createQuery(queryString);
 1121   				prepareQuery(queryObject);
 1122   				if (values != null) {
 1123   					for (int i = 0; i < values.length; i++) {
 1124   						queryObject.setParameter(i, values[i]);
 1125   					}
 1126   				}
 1127   				return queryObject.iterate();
 1128   			}
 1129   		});
 1130   	}
 1131   
 1132   	public void closeIterator(Iterator it) throws DataAccessException {
 1133   		try {
 1134   			Hibernate.close(it);
 1135   		}
 1136   		catch (HibernateException ex) {
 1137   			throw SessionFactoryUtils.convertHibernateAccessException(ex);
 1138   		}
 1139   	}
 1140   
 1141   	public int bulkUpdate(String queryString) throws DataAccessException {
 1142   		return bulkUpdate(queryString, (Object[]) null);
 1143   	}
 1144   
 1145   	public int bulkUpdate(String queryString, Object value) throws DataAccessException {
 1146   		return bulkUpdate(queryString, new Object[] {value});
 1147   	}
 1148   
 1149   	public int bulkUpdate(final String queryString, final Object[] values) throws DataAccessException {
 1150   		Integer updateCount = (Integer) executeWithNativeSession(new HibernateCallback() {
 1151   			public Object doInHibernate(Session session) throws HibernateException {
 1152   				Query queryObject = session.createQuery(queryString);
 1153   				prepareQuery(queryObject);
 1154   				if (values != null) {
 1155   					for (int i = 0; i < values.length; i++) {
 1156   						queryObject.setParameter(i, values[i]);
 1157   					}
 1158   				}
 1159   				return new Integer(queryObject.executeUpdate());
 1160   			}
 1161   		});
 1162   		return updateCount.intValue();
 1163   	}
 1164   
 1165   
 1166   	//-------------------------------------------------------------------------
 1167   	// Helper methods used by the operations above
 1168   	//-------------------------------------------------------------------------
 1169   
 1170   	/**
 1171   	 * Check whether write operations are allowed on the given Session.
 1172   	 * <p>Default implementation throws an InvalidDataAccessApiUsageException in
 1173   	 * case of <code>FlushMode.NEVER/MANUAL</code>. Can be overridden in subclasses.
 1174   	 * @param session current Hibernate Session
 1175   	 * @throws InvalidDataAccessApiUsageException if write operations are not allowed
 1176   	 * @see #setCheckWriteOperations
 1177   	 * @see #getFlushMode()
 1178   	 * @see #FLUSH_EAGER
 1179   	 * @see org.hibernate.Session#getFlushMode()
 1180   	 * @see org.hibernate.FlushMode#NEVER
 1181   	 * @see org.hibernate.FlushMode#MANUAL
 1182   	 */
 1183   	protected void checkWriteOperationAllowed(Session session) throws InvalidDataAccessApiUsageException {
 1184   		if (isCheckWriteOperations() && getFlushMode() != FLUSH_EAGER &&
 1185   				session.getFlushMode().lessThan(FlushMode.COMMIT)) {
 1186   			throw new InvalidDataAccessApiUsageException(
 1187   					"Write operations are not allowed in read-only mode (FlushMode.NEVER/MANUAL): "+
 1188   					"Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.");
 1189   		}
 1190   	}
 1191   
 1192   	/**
 1193   	 * Prepare the given Query object, applying cache settings and/or
 1194   	 * a transaction timeout.
 1195   	 * @param queryObject the Query object to prepare
 1196   	 * @see #setCacheQueries
 1197   	 * @see #setQueryCacheRegion
 1198   	 * @see SessionFactoryUtils#applyTransactionTimeout
 1199   	 */
 1200   	protected void prepareQuery(Query queryObject) {
 1201   		if (isCacheQueries()) {
 1202   			queryObject.setCacheable(true);
 1203   			if (getQueryCacheRegion() != null) {
 1204   				queryObject.setCacheRegion(getQueryCacheRegion());
 1205   			}
 1206   		}
 1207   		if (getFetchSize() > 0) {
 1208   			queryObject.setFetchSize(getFetchSize());
 1209   		}
 1210   		if (getMaxResults() > 0) {
 1211   			queryObject.setMaxResults(getMaxResults());
 1212   		}
 1213   		SessionFactoryUtils.applyTransactionTimeout(queryObject, getSessionFactory());
 1214   	}
 1215   
 1216   	/**
 1217   	 * Prepare the given Criteria object, applying cache settings and/or
 1218   	 * a transaction timeout.
 1219   	 * @param criteria the Criteria object to prepare
 1220   	 * @see #setCacheQueries
 1221   	 * @see #setQueryCacheRegion
 1222   	 * @see SessionFactoryUtils#applyTransactionTimeout
 1223   	 */
 1224   	protected void prepareCriteria(Criteria criteria) {
 1225   		if (isCacheQueries()) {
 1226   			criteria.setCacheable(true);
 1227   			if (getQueryCacheRegion() != null) {
 1228   				criteria.setCacheRegion(getQueryCacheRegion());
 1229   			}
 1230   		}
 1231   		if (getFetchSize() > 0) {
 1232   			criteria.setFetchSize(getFetchSize());
 1233   		}
 1234   		if (getMaxResults() > 0) {
 1235   			criteria.setMaxResults(getMaxResults());
 1236   		}
 1237   		SessionFactoryUtils.applyTransactionTimeout(criteria, getSessionFactory());
 1238   	}
 1239   
 1240   	/**
 1241   	 * Apply the given name parameter to the given Query object.
 1242   	 * @param queryObject the Query object
 1243   	 * @param paramName the name of the parameter
 1244   	 * @param value the value of the parameter
 1245   	 * @throws HibernateException if thrown by the Query object
 1246   	 */
 1247   	protected void applyNamedParameterToQuery(Query queryObject, String paramName, Object value)
 1248   			throws HibernateException {
 1249   
 1250   		if (value instanceof Collection) {
 1251   			queryObject.setParameterList(paramName, (Collection) value);
 1252   		}
 1253   		else if (value instanceof Object[]) {
 1254   			queryObject.setParameterList(paramName, (Object[]) value);
 1255   		}
 1256   		else {
 1257   			queryObject.setParameter(paramName, value);
 1258   		}
 1259   	}
 1260   
 1261   
 1262   	/**
 1263   	 * Invocation handler that suppresses close calls on Hibernate Sessions.
 1264   	 * Also prepares returned Query and Criteria objects.
 1265   	 * @see org.hibernate.Session#close
 1266   	 */
 1267   	private class CloseSuppressingInvocationHandler implements InvocationHandler {
 1268   
 1269   		private final Session target;
 1270   
 1271   		public CloseSuppressingInvocationHandler(Session target) {
 1272   			this.target = target;
 1273   		}
 1274   
 1275   		public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 1276   			// Invocation on Session interface coming in...
 1277   
 1278   			if (method.getName().equals("equals")) {
 1279   				// Only consider equal when proxies are identical.
 1280   				return (proxy == args[0] ? Boolean.TRUE : Boolean.FALSE);
 1281   			}
 1282   			else if (method.getName().equals("hashCode")) {
 1283   				// Use hashCode of Session proxy.
 1284   				return new Integer(System.identityHashCode(proxy));
 1285   			}
 1286   			else if (method.getName().equals("close")) {
 1287   				// Handle close method: suppress, not valid.
 1288   				return null;
 1289   			}
 1290   
 1291   			// Invoke method on target Session.
 1292   			try {
 1293   				Object retVal = method.invoke(this.target, args);
 1294   
 1295   				// If return value is a Query or Criteria, apply transaction timeout.
 1296   				// Applies to createQuery, getNamedQuery, createCriteria.
 1297   				if (retVal instanceof Query) {
 1298   					prepareQuery(((Query) retVal));
 1299   				}
 1300   				if (retVal instanceof Criteria) {
 1301   					prepareCriteria(((Criteria) retVal));
 1302   				}
 1303   
 1304   				return retVal;
 1305   			}
 1306   			catch (InvocationTargetException ex) {
 1307   				throw ex.getTargetException();
 1308   			}
 1309   		}
 1310   	}
 1311   
 1312   }

Save This Page
Home » spring-framework-2.5.6-with-dependencies » org.springframework » orm » hibernate3 » [javadoc | source]