Spring 事务管理

简单说一下事务

''是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。''

四大特性(ACID)
  • 原子性(Atomicity): 指事务不可分割,要么全做,要么都不做。
  • 一致性(Consisitency):指事务完成前后,所有数据保持一致状态。譬如转账操作,前后总额不能改后变。
  • 隔离性(Isolation):指开启事务后,不受其它事务影响。
  • 持久性(Durability):指事务完成后,对数据库记录的修改是永久的。
事务隔离级别

并发的情况下会破坏掉事务的特性,导致操作数据的不一致。情况有以下几种。

  • 脏读
    当前事务读到另一事务未提交的数据。
    我向你转账1元,然后你看到了,给我两个馒头,我拿到馒头走了,接着把事务回滚了。。
  • 不可重复读
    在一个事务中,多次查询同一记录,结果不一致。原因是别的事务修改了该条记录并提交了。
  • 幻读
    开启事务后,两次统计数据库记录条数,结果显示不一致。
    在做统计时就很为难。

解决办法利用锁机制,常用的是乐观锁,为表中添加一个vision字段;或者直接指定会话的隔离级别。

注:不可重复读和幻读都是读取别人以及提交的事务,只是前者是读取一个数据项,后者则是针对一批。

以往对事务的操作

JDBC中

//JDBC中,事务自动提交,得手动打开,(伪代码)
Connection conn =   
    DataSourceUtils.getConnection();  
 //开启事务  
conn.setAutoCommit(false);  
try {  
    Object obj =   
        callback.doInConnection(conn);  
    conn.commit(); //提交事务  
    return retVal;  
}catch (Exception e) {  
    conn.rollback();//回滚事务  
    throw e;  
}finally {  
    conn.close();  
}   

后来交由SessionFactory管理

Session session = factory.openSession();
        try {
            session.beginTransaction();
            //do something
            //session.save(obj);
            session.beginTransaction().commit();
        } catch (HibernateException e) {
            session.beginTransaction().rollback();
            e.printStackTrace();
        } finally {
            if(session != null && session.isOpen()) {
                session.close();
            }
        }

再后来还是得不到满足,因为每个方法都得这样,重复代码过多。而且扩展性很差。于是想到了ThreadLocal模式,即将session放在ThreadLocal变量中。并利用struts2拦截器,自动开启事务,提交事务和关闭事务。但是你需要每次都获取当前线程的session。

@Override
    public String intercept(ActionInvocation invocation) throws Exception {
        String ret = null;
        Session session = null;
        try {
            session = HibernateUtil.getSession();
            session.beginTransaction();
            System.out.println("********获取session开启事务***********");
            ret = invocation.invoke();//该拦截器负责为这次请求创建一个session并管理业务和关闭session
            session.getTransaction().commit();
        } catch (Exception e) {
            session.getTransaction().rollback();
            e.printStackTrace();
        } finally {
            if(session != null && session.isOpen()) {
                System.out.println("********事务结束关闭session***********");
                session.close();
            }
        }
        return ret;
    }

对的,没错,像下面这样获取session。

//ThreadLocal local
public static Session getSession() {
        Session session = local.get();
        if(session == null || !session.isOpen()) {
            session = factory.openSession();
            local.set(session);
        }
        return session;
    }

那么现在,Spring 来了。你不再从应用程序中主动获取资源,你只需要专注你的业务就好。像这种东西,Spring来帮你搞定!

//既然是事务,Spring提供了一个管理事务的类,我们将其注入IoC容器

    
        
        
    
//上面是通过set方法注入了类依赖的对象,我们也要将其注入

//为类中注入了与数据库连接用到的相关参数

        
        
        
        
    

//这个是hibernate自身属性配置

    
        
        
            
                org.hibernate.dialect.MySQLDialect
                true
                update
            
        
        
        
            
                User.hbm.xml
            
        
    

接下来我们要使用AOP,相关注释很明显了。


    
        
            
            
            
            
            
        
    
    
    
        
        
    

为了方便理解,我决定画张图。


AopTx.png

你可能感兴趣的:(Spring 事务管理)