Spring框架学习笔记2:AOP中@Transactional参数小记
Transactional介绍
@Tansactional的功能是将一个函数以一个事务的形式来对待。
@Transactional(rollbackFor ={ArithmeticException.class})
public void buyBook(){
bookDao.getPrice(1);
bookDao.updateBalance("zhangsan",100);
int i=1/0;
bookDao.updateStock(1);
}
@Transaction的一些属性
/*
*
* propagation:传播特性:表示不同事务之间执行的关系
* isolation:隔离级别 4种: 读未提交(read-uncommitted)
不可重复读(read-committed)
可重复读(repeatable-read)
串行化(serializable)
* timeout:超时时间
* readonly:只读事务:如果配置了只读事务,那么在事务运行期间,不允许对事务进行修改,否则抛出异常
* 设置哪些异常不会回滚数据
* noRollbackFor:noRollbackFor={ArithmeticException.class}
* noRollbackForClassName: noRollbackForClassName={java.lang.ArithmeticException}
* 设置哪些异常回滚:
* rollbackFor: rollbackFor={FileNotFoundException.class}
* rollbackForClassName: rollbackForClassName={java.io.FileNotFoundException}
传播特性
REQUIRED:如果有事务在运行,当前的方法就在这个事务内运行。如果没有事务在运行,就启动一个新的事务,并在自己的事务内运行。
REQUIRES_NEW:当前方法必须启动新事务,并在它自己的事务内运行,如果有事务正在运行,则应当将他挂起。
SUPPORTS:如果有事务在运行,当前的方法就运行在事务中,否则,它可以不运行在事务中。
NOT_SUPPORTED:当前的方法不应该运行在事务中,如果有运行的事务,将它挂起。
MANDATORY:当前方法必须运行在事务中,否则报错。
NEVER:当前方法不应该运行在事务中,如果有运行的事务,就会报错。
NESTED:如果有事务运行,当前的方法就在这个事务的嵌套事务内运行,否则,就启动一个新的事务,并在它自己的事务内运行。
值得注意的地方:
1、事务传播级别是REQUIRED,当checkout()被调用时(假定被另一类中commit()调用),如果checkout()中的代码抛出异常,即便被捕获,commit()中的其他代码都会roll back
2、是REQUIRES_NEW,如果checkout()中的代码抛出异常,并且被捕获,commit()中的其他代码不会roll back;如果commit()中的其他代码抛出异常,而且没有捕获,不会导致checkout()回滚
3、是NESTED,如果checkout()中的代码抛出异常,并且被捕获,commit()中的其他代码不会roll back;如果commit()中的其他代码抛出异常,而且没有捕获,会导致checkout()回滚
4、如果在本方法内调用的话,就是一个普通事务内进行普通的调用方法,没有以上的说法。
PROPAGATION_REQUIRES_NEW 启动一个新的, 不依赖于环境的 “内部” 事务. 这个事务将被完全 commited 或 rolled back 而不依赖于外部事务, 它拥有自己的隔离范围, 自己的锁, 等等. 当内部事务开始执行时, 外部事务将被挂起, 内务事务结束时, 外部事务将继续执行.
另一方面, PROPAGATION_NESTED 开始一个 “嵌套的” 事务, 它是已经存在事务的一个真正的子事务. 嵌套事务开始执行时, 它将取得一个 savepoint. 如果这个嵌套事务失败, 我们将回滚到此 savepoint. 潜套事务是外部事务的一部分, 只有外部事务结束后它才会被提交.
由此可见, PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED 的最大区别在于, PROPAGATION_REQUIRES_NEW 完全是一个新的事务, 而 PROPAGATION_NESTED 则是外部事务的子事务, 如果外部事务 commit, 嵌套事务也会被 commit, 这个规则同样适用于 roll back.