Spring事务管理

1、简介

spring支持编程式事务管理和声明式事务管理两种方式。 
编程式事务管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。对于编程式事务管理,spring推荐使用TransactionTemplate。 
声明式事务管理创建在AOP之上的。其本质是对方法先后进行拦截,而后在目标方法开始以前建立或者加入一个事务,在执行完目标方法以后根据执行状况提交或者回滚事务。声明式事务最大的优势就是不须要经过编程的方式管理事务,这样就不须要在业务逻辑代码中掺琐事务管理的代码,只需在配置文件中作相关的事务规则声明(或经过基于@Transactional注解的方式),即可以将事务规则应用到业务逻辑中。html

显然声明式事务管理要优于编程式事务管理,这正是spring倡导的非侵入式的开发方式。声明式事务管理使业务代码不受污染,一个普通的POJO对象,只要加上注解就能够得到彻底的事务支持。和编程式事务相比,声明式事务惟一不足地方是,后者的最细粒度只能做用到方法级别,没法作到像编程式事务那样能够做用到代码块级别。可是即使有这样的需求,也存在不少变通的方法,好比,能够将须要进行事务管理的代码块独立为方法等等。spring

声明式事务管理也有两种经常使用的方式,一种是基于tx和aop名字空间的xml配置文件,另外一种就是基于@Transactional注解。显然基于注解的方式更简单易用,更清爽。数据库

事务有四个特性:ACID 
原子性(Atomicity):事务是一个原子操做,由一系列动做组成。事务的原子性确保动做要么所有完成,要么彻底不起做用。 
一致性(Consistency):一旦事务完成(无论成功仍是失败),系统必须确保它所建模的业务处于一致的状态,而不会是部分完成部分失败。在现实中的数据不该该被破坏。 
隔离性(Isolation):可能有许多事务会同时处理相同的数据,所以每一个事务都应该与其余事务隔离开来,防止数据损坏。 
持久性(Durability):一旦事务完成,不管发生什么系统错误,它的结果都不该该受到影响,这样就能从任何系统崩溃中恢复过来。一般状况下,事务的结果被写到持久化存储器中。编程

2、事务的7个传播行为

事务的传播行为是指,若是在开始当前事务以前,一个事务上下文已经存在,此时有若干选项能够指定一个事务性方法的执行行为。在TransactionDefinition定义中包括了以下几个表示传播行为的常量:并发

一、PROPAGATION_REQUIRED:若是当前存在事务,则加入该事务;若是当前没有事务,则建立一个新的事务。这是默认值;ide

二、PROPAGATION_REQUIRES_NEW:建立一个新的事务,若是当前存在事务,则把当前事务挂起;优化

三、PROPAGATION_SUPPORTS:若是当前存在事务,则加入该事务;若是当前没有事务,则以非事务的方式继续运行;spa

四、PROPAGATION_NOT_SUPPORTED:以非事务方式运行,若是当前存在事务,则把当前事务挂起;code

五、PROPAGATION_NEVER:以非事务方式运行,若是当前存在事务,则抛出异常;orm

六、PROPAGATION_MANDATORY:若是当前存在事务,则加入该事务;若是当前没有事务,则抛出异常;

七、PROPAGATION_NESTED:若是当前存在事务,则建立一个事务做为当前事务的嵌套事务来运行;若是当前没有事务,则该取值等价于PROPAGATION_REQUIRED。

详解参考:Spring事务管理

3、事务的5个隔离级别

先了解什么是 脏数据, 脏读, 不可重复读, 幻读?

脏读: 一个事务正在对数据进行更新操做,可是更新还未提交,另外一个事务这时也来操做这组数据,而且读取了前一个事务还未提交的数据,而前一个事务若是操做失败进行了回滚,后一个事务读取的就是错误数据,这样就形成了脏读。

不可重复读: 一个事务屡次读取同一数据,在该事务还未结束时,另外一个事务也对该数据进行了操做,并且在第一个事务两次次读取之间,第二个事务对数据进行了更新,那么第一个事务先后两次读取到的数据是不一样的,这样就形成了不可重复读。

幻觉读: 幻读与不可重复读相似。它发生在一个事务读取了几行数据,接着另外一个并发事务插入了一些数据时。在随后的查询中,第一个事务就会发现多了一些本来不存在的记录。

事务的隔离级别有如下5种:

一、default

默认的事务隔离级别

二、read_uncommitted

读未提交,一个事务能够操做另一个未提交的事务,不能避免脏读,不可重复读,幻读,隔离级别最低,并发性 能最高

三、read_committed

读已提交,一个事务不能够操做另一个未提交的事务, 能防止脏读,不能避免不可重复读,幻读。

四、repeatable_read

可以避免脏读,不可重复读,不能避免幻读

五、serializable

隔离级别最高,消耗资源最低,代价最高,可以防止脏读, 不可重复读,幻读。

4、代码案例

/**
     * 1.添加事务注解
     * 使用propagation 指定事务的传播行为,即当前的事务方法被另一个事务方法调用时如何使用事务。
     * 默认取值为REQUIRED,即便用调用方法的事务
     * REQUIRES_NEW:使用本身的事务,调用的事务方法的事务被挂起。
     *
     * 2.使用isolation 指定事务的隔离级别,最经常使用的取值为READ_COMMITTED
     * 3.默认状况下 Spring 的声明式事务对全部的运行时异常进行回滚,也能够经过对应的属性进行设置。一般状况下,默认值便可。
     * 4.使用readOnly 指定事务是否为只读。 表示这个事务只读取数据但不更新数据,这样能够帮助数据库引擎优化事务。若真的是一个只读取数据库值得方法,应设置readOnly=true
     * 5.使用timeOut 指定强制回滚以前事务能够占用的时间。
     */
    @Transactional(propagation=Propagation.REQUIRES_NEW,
            isolation=Isolation.READ_COMMITTED,
            noRollbackFor={UserAccountException.class},
            readOnly=true, timeout=3)
    @Override
    public void purchase(String username, String isbn) {
        //1.获取书的单价
        int price = bookShopDao.findBookPriceByIsbn(isbn);
        //2.更新书的库存
        bookShopDao.updateBookStock(isbn);
        //3.更新用户余额
        bookShopDao.updateUserAccount(username, price);
    }
相关文章
相关标签/搜索