hibernatetemplate.java
来自「一个关于Spring框架的示例应用程序,简单使用,可以参考.」· Java 代码 · 共 1,216 行 · 第 1/3 页
JAVA
1,216 行
/*
* Copyright 2002-2004 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.hibernate;
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 net.sf.hibernate.Criteria;
import net.sf.hibernate.FlushMode;
import net.sf.hibernate.Hibernate;
import net.sf.hibernate.HibernateException;
import net.sf.hibernate.LockMode;
import net.sf.hibernate.Query;
import net.sf.hibernate.Session;
import net.sf.hibernate.SessionFactory;
import net.sf.hibernate.type.Type;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
/**
* Helper class that simplifies Hibernate data access code, and converts
* checked HibernateExceptions into unchecked DataAccessExceptions,
* following the <code>org.springframework.dao</code> exception hierarchy.
* Uses the same SQLExceptionTranslator mechanism as JdbcTemplate.
*
* <p>Typically used to implement data access or business logic services that
* use Hibernate within their implementation but are Hibernate-agnostic in their
* interface. The latter or code calling the latter only have to deal with
* domain objects, query objects, and <code>org.springframework.dao</code> exceptions.
*
* <p>The central method is "execute", supporting Hibernate code implementing
* the 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).
*
* <p>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.
*
* <p>This class can be considered a programmatic alternative to
* HibernateInterceptor. The major advantage is its straightforwardness, the
* major disadvantage that no checked application exceptions can get thrown
* from within data access code. Such checks and the actual throwing of such
* exceptions can often be deferred to after callback execution, though.
*
* <p>Note that even if HibernateTransactionManager is used for transaction
* demarcation in higher-level services, all those services above the data
* access layer don't need need to be Hibernate-aware. Setting such a special
* PlatformTransactionManager is a configuration issue: For example,
* switching to JTA is just a matter of Spring configuration (use
* JtaTransactionManager instead) that does not affect application code.
*
* <p>LocalSessionFactoryBean is the preferred way of obtaining a reference
* to a specific Hibernate SessionFactory, at least in a non-EJB environment.
* Alternatively, use a JndiObjectFactoryBean to fetch a SessionFactory
* from JNDI (possibly set up via a JCA Connector).
*
* <p>Note that operations that return an Iterator (i.e. <code>iterate</code>)
* 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.
*
* <p>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>, <code>evict</code>, <code>lock</code>,
* <code>flush</code>, <code>clear</code>.
*
* <p>Note: Spring's Hibernate support requires Hibernate 2.1 (as of Spring 1.0).
*
* @author Juergen Hoeller
* @since 02.05.2003
* @see #setSessionFactory
* @see #setJdbcExceptionTranslator
* @see HibernateCallback
* @see net.sf.hibernate.Session
* @see HibernateInterceptor
* @see LocalSessionFactoryBean
* @see org.springframework.jndi.JndiObjectFactoryBean
* @see org.springframework.jdbc.support.SQLExceptionTranslator
* @see HibernateTransactionManager
* @see org.springframework.transaction.jta.JtaTransactionManager
* @see org.springframework.orm.hibernate.support.OpenSessionInViewFilter
* @see org.springframework.orm.hibernate.support.OpenSessionInViewInterceptor
*/
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;
/**
* Create a new HibernateTemplate instance.
*/
public HibernateTemplate() {
}
/**
* Create a new HibernateTemplate instance.
* @param sessionFactory SessionFactory to create Sessions
*/
public HibernateTemplate(SessionFactory sessionFactory) {
setSessionFactory(sessionFactory);
afterPropertiesSet();
}
/**
* Create a new HibernateTemplate instance.
* @param sessionFactory SessionFactory to create Sessions
* @param allowCreate if a new Session should be created
* if no thread-bound found
*/
public HibernateTemplate(SessionFactory sessionFactory, boolean allowCreate) {
setSessionFactory(sessionFactory);
setAllowCreate(allowCreate);
afterPropertiesSet();
}
/**
* Set if a new Session should be created if no thread-bound found.
* <p>HibernateTemplate is aware of a respective Session bound to the
* current thread, for example when using HibernateTransactionManager.
* If allowCreate is true, a new Session will be created if none found.
* If false, an IllegalStateException will get thrown in this case.
* @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 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).
* <p>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.
* <p>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 alwaysUseNewSession;
}
/**
* Set whether to expose the native Hibernate Session to HibernateCallback
* code. Default is false; instead, a Session proxy will be returned,
* suppressing <code>close</code> calls and automatically applying
* query cache settings and transaction timeouts.
* @see HibernateCallback
* @see net.sf.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 exposeNativeSession;
}
/**
* Set whether to check that the Hibernate Session is not in read-only mode
* in case of write operations (save/update/delete).
* <p>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 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).
* <p>To specify the query region to be used for queries cached
* by this template, set the "queryCacheRegion" property.
* @see #setQueryCacheRegion
* @see net.sf.hibernate.Query#setCacheable
* @see net.sf.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 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).
* <p>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 net.sf.hibernate.Query#setCacheRegion
* @see net.sf.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 queryCacheRegion;
}
public Object execute(HibernateCallback action) throws DataAccessException {
return execute(action, isExposeNativeSession());
}
public List executeFind(HibernateCallback action) throws DataAccessException {
return (List) execute(action, isExposeNativeSession());
}
/**
* Execute the action specified by the given action object within a Session.
* @param action callback object that specifies the Hibernate action
* @param exposeNativeSession whether to expose the native Hibernate Session
* to callback code
* @return a result object returned by the action, or null
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
*/
public Object execute(HibernateCallback action, boolean exposeNativeSession) throws DataAccessException {
Session session = getSession();
boolean existingTransaction = SessionFactoryUtils.isSessionTransactional(session, getSessionFactory());
if (!existingTransaction && getFlushMode() == FLUSH_NEVER) {
session.setFlushMode(FlushMode.NEVER);
}
try {
Session sessionToExpose = (exposeNativeSession ? session : createSessionProxy(session));
Object 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 {
SessionFactoryUtils.closeSessionIfNecessary(session, getSessionFactory());
}
}
/**
* Return a Session for use by this template.
* <p>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
* else (new only if no transactional or otherwise pre-bound Session exists).
* @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(), false);
}
else {
return SessionFactoryUtils.getSession(
getSessionFactory(), getEntityInterceptor(), getJdbcExceptionTranslator());
}
}
/**
* 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 net.sf.hibernate.Session#close
* @see #prepareQuery
* @see #prepareCriteria
*/
protected Session createSessionProxy(Session session) {
return (Session) Proxy.newProxyInstance(
getClass().getClassLoader(),
new Class[] {Session.class},
new CloseSuppressingInvocationHandler(session));
}
//-------------------------------------------------------------------------
// Convenience methods for loading individual objects
//-------------------------------------------------------------------------
public Object get(final Class entityClass, final Serializable id) throws DataAccessException {
return execute(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException {
return session.get(entityClass, id);
}
}, true);
}
public Object get(final Class entityClass, final Serializable id, final LockMode lockMode)
throws DataAccessException {
return execute(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException {
return session.get(entityClass, id, lockMode);
}
}, true);
}
public Object load(final Class entityClass, final Serializable id) throws DataAccessException {
return execute(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException {
return session.load(entityClass, id);
}
}, true);
}
public Object load(final Class entityClass, final Serializable id, final LockMode lockMode)
throws DataAccessException {
return execute(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException {
return session.load(entityClass, id, lockMode);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?