同大家分享一个基于Spring的Hibernate数据库会话及事务拦截器。
背景:
1.Hibernate的Session和Transaction的开关是很烦人的一件事,我们希望有一个拦截器能自动的在我们需要的时候打开session或者transaction,并且在相应方法结束的时候自动关闭
2.Open Session In View是Hibernate官网上推荐的使用Servlet Filter对Session的控制的方式,对一般的web应用还不错,但要用于企业的SOA分布应用就比较困难了
3.如何实现Transaction的自动开关呢?还要考虑到业务方法的嵌套调用,事务的边界是不确定的情况。
下面的这两个类给出了一种简单的解决方式,在实际应用中能提高不少编程效率。
使用条件:
1.使用Spring拦截器,配置你要拦截的类
(我的使用方式是,所有业务逻辑层的类都以Biz做结尾,进行拦截)
2.所有事务性的方法以tx开头
以下是辅助工具类,来自Hibernate官网的,做了些修改和注释
背景:
1.Hibernate的Session和Transaction的开关是很烦人的一件事,我们希望有一个拦截器能自动的在我们需要的时候打开session或者transaction,并且在相应方法结束的时候自动关闭
2.Open Session In View是Hibernate官网上推荐的使用Servlet Filter对Session的控制的方式,对一般的web应用还不错,但要用于企业的SOA分布应用就比较困难了
3.如何实现Transaction的自动开关呢?还要考虑到业务方法的嵌套调用,事务的边界是不确定的情况。
下面的这两个类给出了一种简单的解决方式,在实际应用中能提高不少编程效率。
使用条件:
1.使用Spring拦截器,配置你要拦截的类
(我的使用方式是,所有业务逻辑层的类都以Biz做结尾,进行拦截)
2.所有事务性的方法以tx开头
package org.wltea.util;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.wltea.sql.hibernate.HibernateUtil;
/**
* Hibernate的事务拦截器,通过配置文件自动完成Hibernate的事务
*
* @author linliangyi , zhuoshiyao
*
*/
public class TransactionInterceptor implements MethodInterceptor {
private ThreadLocal<Integer> lockDeep = new ThreadLocal<Integer>();
public Object invoke(MethodInvocation arg0) throws Throwable {
Object result = null;
String methodName = arg0.getMethod().getName();
boolean isBeginTransaction = false;//是否需要开事务
try {
//判断是否需要事务
if (methodName.startsWith("tx")) {
//线程变量中事务数加1
Integer deep = lockDeep.get();
if (deep == null || deep.intValue() == 0) {
deep = new Integer(1);
} else {
deep = new Integer(deep.intValue() + 1);
}
lockDeep.set(deep);
HibernateUtil.beginTransaction();//开始事务
isBeginTransaction = true;//标志事务已打开
}
//执行业务逻辑方法
result = arg0.proceed();
if (isBeginTransaction) {
//线程变量
int deep = lockDeep.get().intValue();
deep = deep - 1;
if (deep == 0) {
HibernateUtil.commitTransaction();//提交事务
}
//若正常提交事务,线程变量中事务数减1
lockDeep.set(new Integer(deep));
}
} catch(Exception e) {
if (isBeginTransaction) {
//线程变量
int deep = lockDeep.get().intValue();
deep = deep - 1;
//线程变量中事务数减1
lockDeep.set(new Integer(deep));
HibernateUtil.rollbackTransaction();//异常则回滚DB事务
}
throw e;
} finally {
Integer deep = lockDeep.get();
if (deep == null || deep.intValue() == 0) {
HibernateUtil.closeSession();//如果上下文有开启的session,关闭session
}
}
return result;
}
}
以下是辅助工具类,来自Hibernate官网的,做了些修改和注释
package org.wltea.sql.hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
/**
*
* Hibernate工具类
*
* 单子模式类
* 提供了方便的,静态的session及Transaction获取,关闭方法。
* 使用ThreadLocal对象维护session在一个线程操作(通常也是事务操作)中的唯一性
*
* Configures and provides access to Hibernate sessions, tied to the
* current thread of execution. Follows the Thread Local Session
* pattern, see {@link http://hibernate.org/42.html }.
*/
public class HibernateUtil {
/**
* Location of hibernate.cfg.xml file.
* Location should be on the classpath as Hibernate uses
* #resourceAsStream style lookup for its configuration file.
* The default classpath location of the hibernate config file is
* in the default package. Use #setConfigFile() to update
* the location of the configuration file for the current session.
*/
private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";
private static final ThreadLocal localSession = new ThreadLocal();
private static final ThreadLocal localTransaction = new ThreadLocal();
private static Configuration configuration = new Configuration();
private static SessionFactory sessionFactory;
private static String configFile = CONFIG_FILE_LOCATION;
static {
try {
configuration.configure(configFile);
sessionFactory = configuration.buildSessionFactory();
} catch (Exception e) {
System.err
.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
}
private HibernateUtil() {
}
/**
* Returns the ThreadLocal Session instance. Lazy initialize
* the <code>SessionFactory</code> if needed.
*
* @return Session
* @throws HibernateException
*/
public static Session getSession() throws HibernateException {
Session session = (Session) localSession.get();
if (session == null || !session.isOpen()) {
if (sessionFactory == null) {
rebuildSessionFactory();
}
session = (sessionFactory != null) ? sessionFactory.openSession()
: null;
localSession.set(session);
}
return session;
}
/**
* Rebuild hibernate session factory
*
*/
public static void rebuildSessionFactory() {
try {
configuration.configure(configFile);
sessionFactory = configuration.buildSessionFactory();
} catch (Exception e) {
System.err.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
}
/**
* Close the single hibernate session instance.
*
* @throws HibernateException
*/
public static void closeSession() throws HibernateException {
Session session = (Session) localSession.get();
localSession.set(null);
if (session != null && session.isOpen()) {
session.close();
}
}
/**
* return session factory
*
*/
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
/**
* return session factory
*
* session factory will be rebuilded in the next call
*/
public static void setConfigFile(String configFile) {
HibernateUtil.configFile = configFile;
sessionFactory = null;
}
/**
* return hibernate configuration
*
*/
public static Configuration getConfiguration() {
return configuration;
}
/**
* 开始当前线程中Hibernate Session的事务
* @return Transaction
* @throws HibernateException
*/
public static Transaction beginTransaction() throws HibernateException {
Transaction tx = (Transaction)localTransaction.get();
if(tx == null || tx.wasCommitted() || tx.wasRolledBack()){
Session session = getSession();
tx = (session != null) ? session.beginTransaction() : null;
localTransaction.set(tx);
}
return tx;
}
/**
* 提交当前线程中Hibernate Session的事务
* @throws HibernateException
*/
public static void commitTransaction() throws HibernateException {
Transaction tx = (Transaction)localTransaction.get();
localTransaction.set(null);
if(tx != null || (!tx.wasCommitted() && !tx.wasRolledBack())){
tx.commit();
}
}
/**
* 回滚当前线程中Hibernate Session的事务
* @throws HibernateException
*/
public static void rollbackTransaction() throws HibernateException {
Transaction tx = (Transaction)localTransaction.get();
localTransaction.set(null);
if(tx != null || (!tx.wasCommitted() && !tx.wasRolledBack())){
tx.rollback();
}
}
/**
* 当前Hibernate Session是否打开
* @return
*/
public static boolean isOpenSession() {
Session session = (Session) localSession.get();
if (session != null && session.isOpen()) {
return true;
}
return false;
}
}