Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.orm.hibernate3;
import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Filter;
import org.hibernate.FlushMode;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.Query;
import org.hibernate.ReplicationMode;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Example;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.event.EventSource;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.util.Assert;
/**
* Helper class that simplifies Hibernate data access code. Automatically
* converts HibernateExceptions into DataAccessExceptions, following the
* {@code org.springframework.dao} exception hierarchy.
*
*
The central method is {@code execute}, supporting Hibernate access code
* implementing the {@link HibernateCallback} interface. It provides Hibernate Session
* handling such that neither the HibernateCallback implementation nor the calling
* code needs to explicitly care about retrieving/closing Hibernate Sessions,
* or handling Session lifecycle exceptions. For typical single step actions,
* there are various convenience methods (find, load, saveOrUpdate, delete).
*
*
Can be used within a service implementation via direct instantiation
* with a SessionFactory reference, or get prepared in an application context
* and given to services as bean reference. Note: The SessionFactory should
* always be configured as bean in the application context, in the first case
* given to the service directly, in the second case to the prepared template.
*
*
NOTE: As of Hibernate 3.0.1, transactional Hibernate access code can
* also be coded in plain Hibernate style. Hence, for newly started projects,
* consider adopting the standard Hibernate3 style of coding data access objects
* instead, based on {@link org.hibernate.SessionFactory#getCurrentSession()}.
*
*
This class can be considered as direct alternative to working with the raw
* Hibernate3 Session API (through {@code SessionFactory.getCurrentSession()}).
* The major advantage is its automatic conversion to DataAccessExceptions as well
* as its capability to fall back to 'auto-commit' style behavior when used outside
* of transactions. Note that HibernateTemplate will perform its own Session
* management, not participating in a custom Hibernate CurrentSessionContext
* unless you explicitly switch {@link #setAllowCreate "allowCreate"} to "false".
*
*
{@link LocalSessionFactoryBean} is the preferred way of obtaining a reference
* to a specific Hibernate SessionFactory, at least in a non-EJB environment.
* The Spring application context will manage its lifecycle, initializing and
* shutting down the factory as part of the application.
*
*
Note that operations that return an Iterator (i.e. {@code iterate})
* are supposed to be used within Spring-driven or JTA-driven transactions
* (with HibernateTransactionManager, JtaTransactionManager, or EJB CMT).
* Else, the Iterator won't be able to read results from its ResultSet anymore,
* as the underlying Hibernate Session will already have been closed.
*
*
Lazy loading will also just work with an open Hibernate Session,
* either within a transaction or within OpenSessionInViewFilter/Interceptor.
* Furthermore, some operations just make sense within transactions,
* for example: {@code contains}, {@code evict}, {@code lock},
* {@code flush}, {@code clear}.
*
* @author Juergen Hoeller
* @since 1.2
* @see #setSessionFactory
* @see HibernateCallback
* @see org.hibernate.Session
* @see LocalSessionFactoryBean
* @see HibernateTransactionManager
* @see org.springframework.transaction.jta.JtaTransactionManager
* @see org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
* @see org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor
*/
@SuppressWarnings("deprecation")
public class HibernateTemplate extends HibernateAccessor implements HibernateOperations {
private boolean allowCreate = true;
private boolean alwaysUseNewSession = false;
private boolean exposeNativeSession = false;
private boolean checkWriteOperations = true;
private boolean cacheQueries = false;
private String queryCacheRegion;
private int fetchSize = 0;
private int maxResults = 0;
/**
* Create a new HibernateTemplate instance.
*/
public HibernateTemplate() {
}
/**
* Create a new HibernateTemplate instance.
* @param sessionFactory the SessionFactory to create Sessions with
*/
public HibernateTemplate(SessionFactory sessionFactory) {
setSessionFactory(sessionFactory);
afterPropertiesSet();
}
/**
* Create a new HibernateTemplate instance.
* @param sessionFactory the SessionFactory to create Sessions with
* @param allowCreate if a non-transactional Session should be created when no
* transactional Session can be found for the current thread
*/
public HibernateTemplate(SessionFactory sessionFactory, boolean allowCreate) {
setSessionFactory(sessionFactory);
setAllowCreate(allowCreate);
afterPropertiesSet();
}
/**
* Set if a new {@link Session} should be created when no transactional
* {@code Session} can be found for the current thread.
* The default value is {@code true}.
*
{@code HibernateTemplate} is aware of a corresponding
* {@code Session} bound to the current thread, for example when using
* {@link HibernateTransactionManager}. If {@code allowCreate} is
* {@code true}, a new non-transactional {@code Session} will be
* created if none is found, which needs to be closed at the end of the operation.
* If {@code false}, an {@link IllegalStateException} will get thrown in
* this case.
*
NOTE: As of Spring 2.5, switching {@code allowCreate}
* to {@code false} will delegate to Hibernate's
* {@link org.hibernate.SessionFactory#getCurrentSession()} method,
* which - with Spring-based setup - will by default delegate to Spring's
* {@code SessionFactoryUtils.getSession(sessionFactory, false)}.
* This mode also allows for custom Hibernate CurrentSessionContext strategies
* to be plugged in, whereas {@code allowCreate} set to {@code true}
* will always use a Spring-managed Hibernate Session.
* @see SessionFactoryUtils#getSession(SessionFactory, boolean)
*/
public void setAllowCreate(boolean allowCreate) {
this.allowCreate = allowCreate;
}
/**
* Return if a new Session should be created if no thread-bound found.
*/
public boolean isAllowCreate() {
return this.allowCreate;
}
/**
* Set whether to always use a new Hibernate Session for this template.
* Default is "false"; if activated, all operations on this template will
* work on a new Hibernate Session even in case of a pre-bound Session
* (for example, within a transaction or OpenSessionInViewFilter).
*
Within a transaction, a new Hibernate Session used by this template
* will participate in the transaction through using the same JDBC
* Connection. In such a scenario, multiple Sessions will participate
* in the same database transaction.
*
Turn this on for operations that are supposed to always execute
* independently, without side effects caused by a shared Hibernate Session.
*/
public void setAlwaysUseNewSession(boolean alwaysUseNewSession) {
this.alwaysUseNewSession = alwaysUseNewSession;
}
/**
* Return whether to always use a new Hibernate Session for this template.
*/
public boolean isAlwaysUseNewSession() {
return this.alwaysUseNewSession;
}
/**
* Set whether to expose the native Hibernate Session to
* HibernateCallback code.
*
Default is "false": a Session proxy will be returned, suppressing
* {@code close} calls and automatically applying query cache
* settings and transaction timeouts.
* @see HibernateCallback
* @see org.hibernate.Session
* @see #setCacheQueries
* @see #setQueryCacheRegion
* @see #prepareQuery
* @see #prepareCriteria
*/
public void setExposeNativeSession(boolean exposeNativeSession) {
this.exposeNativeSession = exposeNativeSession;
}
/**
* Return whether to expose the native Hibernate Session to
* HibernateCallback code, or rather a Session proxy.
*/
public boolean isExposeNativeSession() {
return this.exposeNativeSession;
}
/**
* Set whether to check that the Hibernate Session is not in read-only mode
* in case of write operations (save/update/delete).
*
Default is "true", for fail-fast behavior when attempting write operations
* within a read-only transaction. Turn this off to allow save/update/delete
* on a Session with flush mode NEVER.
* @see #setFlushMode
* @see #checkWriteOperationAllowed
* @see org.springframework.transaction.TransactionDefinition#isReadOnly
*/
public void setCheckWriteOperations(boolean checkWriteOperations) {
this.checkWriteOperations = checkWriteOperations;
}
/**
* Return whether to check that the Hibernate Session is not in read-only
* mode in case of write operations (save/update/delete).
*/
public boolean isCheckWriteOperations() {
return this.checkWriteOperations;
}
/**
* Set whether to cache all queries executed by this template.
*
If this is "true", all Query and Criteria objects created by
* this template will be marked as cacheable (including all
* queries through find methods).
*
To specify the query region to be used for queries cached
* by this template, set the "queryCacheRegion" property.
* @see #setQueryCacheRegion
* @see org.hibernate.Query#setCacheable
* @see org.hibernate.Criteria#setCacheable
*/
public void setCacheQueries(boolean cacheQueries) {
this.cacheQueries = cacheQueries;
}
/**
* Return whether to cache all queries executed by this template.
*/
public boolean isCacheQueries() {
return this.cacheQueries;
}
/**
* Set the name of the cache region for queries executed by this template.
*
If this is specified, it will be applied to all Query and Criteria objects
* created by this template (including all queries through find methods).
*
The cache region will not take effect unless queries created by this
* template are configured to be cached via the "cacheQueries" property.
* @see #setCacheQueries
* @see org.hibernate.Query#setCacheRegion
* @see org.hibernate.Criteria#setCacheRegion
*/
public void setQueryCacheRegion(String queryCacheRegion) {
this.queryCacheRegion = queryCacheRegion;
}
/**
* Return the name of the cache region for queries executed by this template.
*/
public String getQueryCacheRegion() {
return this.queryCacheRegion;
}
/**
* Set the fetch size for this HibernateTemplate. This is important for processing
* large result sets: Setting this higher than the default value will increase
* processing speed at the cost of memory consumption; setting this lower can
* avoid transferring row data that will never be read by the application.
*
Default is 0, indicating to use the JDBC driver's default.
*/
public void setFetchSize(int fetchSize) {
this.fetchSize = fetchSize;
}
/**
* Return the fetch size specified for this HibernateTemplate.
*/
public int getFetchSize() {
return this.fetchSize;
}
/**
* Set the maximum number of rows for this HibernateTemplate. This is important
* for processing subsets of large result sets, avoiding to read and hold
* the entire result set in the database or in the JDBC driver if we're
* never interested in the entire result in the first place (for example,
* when performing searches that might return a large number of matches).
*
Default is 0, indicating to use the JDBC driver's default.
*/
public void setMaxResults(int maxResults) {
this.maxResults = maxResults;
}
/**
* Return the maximum number of rows specified for this HibernateTemplate.
*/
public int getMaxResults() {
return this.maxResults;
}
@Override
public T execute(HibernateCallback action) throws DataAccessException {
return doExecute(action, false, false);
}
@Override
@Deprecated
@SuppressWarnings("unchecked")
public List executeFind(HibernateCallback action) throws DataAccessException {
Object result = doExecute(action, false, false);
if (result != null && !(result instanceof List)) {
throw new InvalidDataAccessApiUsageException(
"Result object returned from HibernateCallback isn't a List: [" + result + "]");
}
return (List) result;
}
/**
* Execute the action specified by the given action object within a
* new {@link org.hibernate.Session}.
*
This execute variant overrides the template-wide
* {@link #isAlwaysUseNewSession() "alwaysUseNewSession"} setting.
* @param action callback object that specifies the Hibernate action
* @return a result object returned by the action, or {@code null}
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
*/
public T executeWithNewSession(HibernateCallback action) {
return doExecute(action, true, false);
}
/**
* Execute the action specified by the given action object within a
* native {@link org.hibernate.Session}.
*
This execute variant overrides the template-wide
* {@link #isExposeNativeSession() "exposeNativeSession"} setting.
* @param action callback object that specifies the Hibernate action
* @return a result object returned by the action, or {@code null}
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
*/
public T executeWithNativeSession(HibernateCallback action) {
return doExecute(action, false, true);
}
/**
* Execute the action specified by the given action object within a Session.
* @param action callback object that specifies the Hibernate action
* @param enforceNewSession whether to enforce a new Session for this template
* even if there is a pre-bound transactional Session
* @param enforceNativeSession whether to enforce exposure of the native
* Hibernate Session to callback code
* @return a result object returned by the action, or {@code null}
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
*/
protected T doExecute(HibernateCallback action, boolean enforceNewSession, boolean enforceNativeSession)
throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
Session session = (enforceNewSession ?
SessionFactoryUtils.getNewSession(getSessionFactory(), getEntityInterceptor()) : getSession());
boolean existingTransaction = (!enforceNewSession &&
(!isAllowCreate() || SessionFactoryUtils.isSessionTransactional(session, getSessionFactory())));
if (existingTransaction) {
logger.debug("Found thread-bound Session for HibernateTemplate");
}
FlushMode previousFlushMode = null;
try {
previousFlushMode = applyFlushMode(session, existingTransaction);
enableFilters(session);
Session sessionToExpose =
(enforceNativeSession || isExposeNativeSession() ? session : createSessionProxy(session));
T result = action.doInHibernate(sessionToExpose);
flushIfNecessary(session, existingTransaction);
return result;
}
catch (HibernateException ex) {
throw convertHibernateAccessException(ex);
}
catch (SQLException ex) {
throw convertJdbcAccessException(ex);
}
catch (RuntimeException ex) {
// Callback code threw application exception...
throw ex;
}
finally {
if (existingTransaction) {
logger.debug("Not closing pre-bound Hibernate Session after HibernateTemplate");
disableFilters(session);
if (previousFlushMode != null) {
session.setFlushMode(previousFlushMode);
}
}
else {
// Never use deferred close for an explicitly new Session.
if (isAlwaysUseNewSession()) {
SessionFactoryUtils.closeSession(session);
}
else {
SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, getSessionFactory());
}
}
}
}
/**
* Return a Session for use by this template.
*
Returns a new Session in case of "alwaysUseNewSession" (using the same
* JDBC Connection as a transactional Session, if applicable), a pre-bound
* Session in case of "allowCreate" turned off, and a pre-bound or new Session
* otherwise (new only if no transactional or otherwise pre-bound Session exists).
* @return the Session to use (never {@code null})
* @see SessionFactoryUtils#getSession
* @see SessionFactoryUtils#getNewSession
* @see #setAlwaysUseNewSession
* @see #setAllowCreate
*/
protected Session getSession() {
if (isAlwaysUseNewSession()) {
return SessionFactoryUtils.getNewSession(getSessionFactory(), getEntityInterceptor());
}
else if (isAllowCreate()) {
return SessionFactoryUtils.getSession(
getSessionFactory(), getEntityInterceptor(), getJdbcExceptionTranslator());
}
else if (SessionFactoryUtils.hasTransactionalSession(getSessionFactory())) {
return SessionFactoryUtils.getSession(getSessionFactory(), false);
}
else {
try {
return getSessionFactory().getCurrentSession();
}
catch (HibernateException ex) {
throw new DataAccessResourceFailureException("Could not obtain current Hibernate Session", ex);
}
}
}
/**
* Create a close-suppressing proxy for the given Hibernate Session.
* The proxy also prepares returned Query and Criteria objects.
* @param session the Hibernate Session to create a proxy for
* @return the Session proxy
* @see org.hibernate.Session#close()
* @see #prepareQuery
* @see #prepareCriteria
*/
protected Session createSessionProxy(Session session) {
Class[] sessionIfcs;
Class mainIfc = (session instanceof org.hibernate.classic.Session ?
org.hibernate.classic.Session.class : Session.class);
if (session instanceof EventSource) {
sessionIfcs = new Class[] {mainIfc, EventSource.class};
}
else if (session instanceof SessionImplementor) {
sessionIfcs = new Class[] {mainIfc, SessionImplementor.class};
}
else {
sessionIfcs = new Class[] {mainIfc};
}
return (Session) Proxy.newProxyInstance(
session.getClass().getClassLoader(), sessionIfcs,
new CloseSuppressingInvocationHandler(session));
}
//-------------------------------------------------------------------------
// Convenience methods for loading individual objects
//-------------------------------------------------------------------------
@Override
public T get(Class entityClass, Serializable id) throws DataAccessException {
return get(entityClass, id, null);
}
@Override
public T get(final Class entityClass, final Serializable id, final LockMode lockMode)
throws DataAccessException {
return executeWithNativeSession(new HibernateCallback() {
@Override
@SuppressWarnings("unchecked")
public T doInHibernate(Session session) throws HibernateException {
if (lockMode != null) {
return (T) session.get(entityClass, id, lockMode);
}
else {
return (T) session.get(entityClass, id);
}
}
});
}
@Override
public Object get(String entityName, Serializable id) throws DataAccessException {
return get(entityName, id, null);
}
@Override
public Object get(final String entityName, final Serializable id, final LockMode lockMode)
throws DataAccessException {
return executeWithNativeSession(new HibernateCallback