先看一个timeout:单位是秒。下图 timeout = 4
readOnly是只读事务:
应用场合:
若一次执行单条查询语句,则没必要启用事务支持,数据库默认支持SQL执行期间的读一致性
若一次执行多条查询语句,例如统计查询,报表查询,在这种场景下,多条查询SQL必须保证整体的读一致性,否则,在前条SQL查询之后,后条SQL查询之前,数据被其他用户改变,则该次整体的统计查询将会出现读数据不一致的状态,此时,应该启用事务支持。
注意是一次执行多次查询来统计某些信息,这时为了保证数据整体的一致性,要用只读事务
什么是运行时异常?就是运行的时候报错,例如 int i =1/0,数组下标越界等
而编译时异常就是:例如IOException:操作输入流和输出流时可能出现的异常。 EOFException 文件已结束异常 FileNotFoundException 文件未找到异常
先来看 运行时异常 默认是回滚,所以不扣钱
再看编译时异常:由于编译时异常默认是不回滚的,所以造成了在new FileInputStream处报错,代码停止。而之前的扣钱不回滚。
noRollbackFor,表示不回滚 。RollbackFor表示回滚,
这就属于不是默认的方式了,自己手动指定回滚还是不回滚。
在bookDao中新增加了一个修改图书价格的方法:
这就是在controller的x方法里调用了两个带有@Transactional(propagation = Propagation.REQUIRED)事务的方法
而@Transactional()默认的就是propagation = Propagation.REQUIRED
所以x方法上的Transactional其实也是propagation = Propagation.REQUIRED
好了,现在看调用结果:
数据库回到初始状态下运行。
可以看到没有报错的情况下,运行的时候是好的,库存减了,用户钱扣了,价格也调整了。
现在把数据库表数据调整到初始状态。在service里制造错误,这里只讨论RuntimeException,因为RuntimeException是默认回滚的。
运行结果是,数据不变,因为由于 算数运算错误,导致checkout方法回滚。checkout方法又在x方法里,因为checkout算数错误,不但回滚自己的事务,并且x的整个事务也回滚了,所以updatePrice()方法更新价格也是白白更新了。
假如x不加事务怎么办
这拿头想一下都知道,这不就是最初的方法调用么,updatePrice和checkout没关系,所以当checkout报错回滚,updatePrice早都执行完毕了。所以价格也改了。
那假如:checkout和updatePrice 都没错误,而x有错误呢?
还是一样 这三行代码组成新事务,这里报错了,所以 checkout回滚。
现在有3个方法都 T() A() B() 都加了
@Transactional(propagation = Propagation.REQUIRED)
T 依次调用了 AB A 运行中报错, T中 A 之前的代码回滚,并且A 回滚
T 依次调用了 AB B 运行中报错, T中 B之前的代码回滚。(A在B 之前所以A当然回滚了)
T 调用了 AB AB之间的代码报错,则A回滚,因为执行不到B方法
---
T 没有事务,但是AB有事务,那么
T 依次调用了 AB,A运行中报错,则A之前的不回滚,A回滚,因为执行不到B,所以B不回滚
大概get到意思了吧。这是默认的@Transactional(propagation = Propagation.REQUIRED)
再来看:@Transactional(propagation = Propagation.REQUIRES_NEW)
测事务肯定是要有报错的,所以不发生错误的代码就不再运行了,下来开始造错误
给checkout加的是requires_new
运行结果是checkout回滚。updatePrice回滚。checkout肯定是回滚的是报错了,而checkout又在x方法的最后一行,所以x方法报错,所以x方法里面的checkout之前的内容也得回滚。
x方法里变一下调用顺序:
这是什么意思,所谓的requires_new意思是,自己管理事务,不受外界事物干扰。所以当updatePrice发生了错误后,虽然这是x中的最后一行代码,但是之前的checkout是requires_new的,不受外界的x方法的事务控制,所以checkout是不回滚的,
那么给updatePrice变成requires_new呢?变成了两个都是requires_new。还是一样啊,updatePrice报错,自己肯定是要回滚的,但是前面的checkout不会回滚。
这个应用在哪里呢?假设有一个批量提交信用卡还款的方法,方法里面是很多信用卡还款的业务,那么不应该因为中间某一张卡还款失败,而把之前的卡还款的就给回滚,这样做是不对的。卡和卡之间还款是互相不干扰的。
support :
测试 用test类,new controller对象调用 buybook方法,checkout是回滚的,因为 算数异常了,但是去掉buybook的transactional注解,就不回滚了。这个意思是有事务了,就运行事务,没有了就不运行事务控制。
not_supported
这个代码是不回滚的。。。外面buybook的事务加不加都不回滚
never:当前方法不应该在事务内运行,如果在事务内运行,则抛出异常。不涉及到数据库数据的执行,所以也就当是回滚了!!
当改成requires_new后再试试捕获异常:
记住,A调用B方法,在A内trycatch B方法的异常的话,B方法是要回滚事务的。
NESTED
这是新的NESTED,checkout回滚,updatePrice回滚
但是变成了 requires_new之后,checkout不回滚,updatePrice回滚,这块和NESTED比较一下,就是checkout回滚不回滚的问题了,可以想一下requires_new肯定是不回滚的,因为不受外界事物控制
网站声明:如果转载,请联系本站管理员。否则一切后果自行承担。
添加我为好友,拉您入交流群!
请使用微信扫一扫!