首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > 其他数据库 >

分享一个容易的数据库事务拦截器

2012-10-31 
分享一个简单的数据库事务拦截器同大家分享一个基于Spring的Hibernate数据库会话及事务拦截器。背景:1.Hibe

分享一个简单的数据库事务拦截器
同大家分享一个基于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;}}



以下是辅助工具类,来自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;    }    }



莫名其妙,我这不是告诉你了么
怎么就成了显摆了? 12 楼 linliangyi2007 2008-12-09   xucons 写道
xuyao 写道spring当初出来的时候最有名的就是AOP,声明性事务。楼主相当于自己用动态代理实现了一下,呵呵
是啊!我觉得也没有spring实现的好用

xuyao 写道
spring当初出来的时候最有名的就是AOP,声明性事务。楼主相当于自己用动态代理实现了一下,呵呵


当初一直觉得AOP实际上是破坏设计的东西,因为它必须依靠虚拟机或者类加载器注入,就没去太注意它了,呵呵 13 楼 meconsea 2008-12-09   把事务处理做成Annotation,Target=Method.这样 直接@Transcation。o(∩_∩)o...哈哈
14 楼 fhjxp 2008-12-12   meconsea 写道把事务处理做成Annotation,Target=Method.这样 直接@Transcation。o(∩_∩)o...哈哈

这样就还可避免方法名前面加tx、类名后面加Biz。 15 楼 shenrd666888 2009-03-16   spring aop中的声明事物,嗯个强大
哪里还需要自己写嘛
要站在巨人的肩膀上塞 呵呵 16 楼 linliangyi2007 2009-03-16   shenrd666888 写道spring aop中的声明事物,嗯个强大
哪里还需要自己写嘛
要站在巨人的肩膀上塞 呵呵

楼上的见笑了

热点排行