事务管理方式
1. 编程式事务管理
2. 声明式事务管理
建立于AOP之上,对指定的方法执行前后进行拦截,即在方法执行前开始或加入一个事务,执行完毕后根据结果提交或回滚事务。
方式:
a. 配置文件中声明
b. Transaction注解(推荐)
对比:
1. 声明式事务管理使业务代码不受污染,这正是spring倡导的非侵入式的开发方式。
2. 声明式事务管理的细粒度最多只能到方法级别,无法做到像编程式事务那样可以作用到代码块级别。
自动提交
对于数据库,默认情况下,是处于自动提交模式。每一条语句处于一个单独的事务中,执行完毕时,成功则隐式的提交事务,如果失败则隐式的回滚事务。
对于连接池,部分连接池提供了关闭事务自动提交的设置。
对于Spring,它会将底层连接的自动提交特性设置为false,即不会立即到达数据库。
连接关闭时的事务处理
当连接关闭时,如果有未提交的事务应该如何处理?一般的数据库会是回滚任何未提交的事务。
事务管理类
spring所有的事务管理类都继承自org.springframework.transaction.PlatformTransactionManager接口
public interface PlatformTransactionManager { //获取事务状态
//TransactionDefinition对象 TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException; //提交 void commit(TransactionStatus status) throws TransactionException; //回滚 void rollback(TransactionStatus status) throws TransactionException; }
这里重点说一下Transaction接口,它定义了事务的很多特性:
事务隔离级别
指若干个并发的事务之间的隔离程度。
TransactionDefinition.ISOLATION_DEFAULT:这是默认值,表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常这值就是TransactionDefinition.ISOLATION_READ_COMMITTED。
TransactionDefinition.ISOLATION_READ_UNCOMMITTED:该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读,不可重复读和幻读,因此很少使用该隔离级别。比如PostgreSQL实际上并没有此级别。
TransactionDefinition.ISOLATION_READ_COMMITTED:该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。
TransactionDefinition.ISOLATION_REPEATABLE_READ:该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。该级别可以防止脏读和不可重复读。
TransactionDefinition.ISOLATION_SERIALIZABLE:所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。
事务传播行为
指的是在开始当前事务之前,如果另一个事务上下文已经存在,这时该如何处理。
TransactionDefinition.PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。
TransactionDefinition.PROPAGATION_REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。
TransactionDefinition.PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
TransactionDefinition.PROPAGATION_NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。
事务超时时间
指一个事务所允许执行的最长时间,如果超过时间限制但事务还没有完成,则自动回滚事务。
--------------------------------------------------------------------------------------------------------------------------------------------------------------
事务回滚规则
如果触发回滚?
推荐方法是在当前事务对象的上下文内抛出异常,这样spring事务管理器会捕捉此异常,然后依据规则决定是否回滚抛出异常的事务。
根据什么样的规则呢?
默认配置下,只有在抛出的异常为运行时unchecked异常时才回滚该事务,也即抛出的异常为RuntimeException的子类(Errors也会导致事务回滚),而当抛出checked异常则不会导致事务回滚。
但我们可以明确的配置在抛出哪些异常时回滚事务,包括checked异常。也可以明确定义哪些异常抛出时不回滚事务。
还可以编程性的通过setRollbackOnly()方法来指示一个事务必须回滚,在调用完setRollbackOnly()后你所能执行的唯一操作就是回滚。
定义一个事务对象
@Transactional注解(推荐)
通过它能设置上文介绍的多个属性
属性 | 类型 | 描述 |
---|---|---|
value | String | 可选的限定描述符,指定使用的事务管理器 |
propagation | enum: Propagation | 可选的事务传播行为设置 |
isolation | enum: Isolation | 可选的事务隔离级别设置 |
readOnly | boolean | 读写或只读事务,默认读写 |
timeout | int (in seconds granularity) | 事务超时时间设置 |
rollbackFor | Class对象数组,必须继承自Throwable | 导致事务回滚的异常类数组 |
rollbackForClassName | 类名数组,必须继承自Throwable | 导致事务回滚的异常类名字数组 |
noRollbackFor | Class对象数组,必须继承自Throwable | 不会导致事务回滚的异常类数组 |
noRollbackForClassName | 类名数组,必须继承自Throwable | 不会导致事务回滚的异常类名字数组 |
作用范围:接口、接口方法、类、类方法
类
该类的所有public方法将都具有该类型的事务属性
类方法
该方法将都具有该类型的事务属性,且可以覆盖类级别的定义
接口、接口方法
不建议使用