Spring事务管理

来源:互联网 发布:js二维映射 编辑:程序博客网 时间:2024/06/11 14:09

一、简介

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

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

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

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

二、事务的7个传播行为

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

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

2、PROPAGATION_REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则把当前事务挂起;

3、PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行;

4、PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起;

5、PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常;

6、PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常;

7、PROPAGATION_NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于PROPAGATION_REQUIRED。

详解参考:Spring事务管理

三、事务的5个隔离级别

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

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

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

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

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

1、default

默认的事务隔离级别

2、read_uncommitted

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

3、read_committed

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

4、repeatable_read

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

5、serializable

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

四、代码案例

/**     * 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);    }

参考:原文

原创粉丝点击