分享一个简单的数据库事务拦截器
同大家分享一个基于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开头
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")) {//线程变量中事务数加1Integer 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();//提交事务}//若正常提交事务,线程变量中事务数减1lockDeep.set(new Integer(deep));}} catch(Exception e) {if (isBeginTransaction) {//线程变量int deep = lockDeep.get().intValue();deep = deep - 1;//线程变量中事务数减1lockDeep.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;}}
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; } }