spring @Transactional如何测试事务注解生效

spring 事务部分共5篇文章

第一篇:spring中@EnableTransactionManager @Transactional注解实现机制

第二篇:spring boot中事务功能自动配置的加载过程分析

第三篇:spring@Transactional注解属性字段含义

第四篇:spring @Transactional如何测试事务注解生效

第五篇:spring及spring boot中事务相关知识的总结

本篇为第四篇

 

需求:在bo中要操作两张表,insert表1,根据insert的结果update表2。这是一个典型的spring事务的应用情形。在方法上使用@Transactional,如何进行测试,看事务是否起作用了呢?

 

解决方法:常用的测试方法是加入一条b=0;c=a/b;模拟出错的情况。测试应该包括insert表1的过程出错,以及update表2的过程出错。想到的另一种测试方法是修改表名,模拟出错的情况。

 

另外,在debug过程中发现,当执行了insert表1之后,还未执行update表2的时候,表1实际上并没有新增一条记录(这个要看查询线程处在什么隔离级别,如果处在read uncommitted下,那么其是能看到的,即发生“脏读”现象)。而在update表2执行完成之后,会在表1和表2同时新增或更新。

 

“默认情况下,数据库处于自动提交模式。每一条语句处于一个单独的事务中,在这条语句执行完毕时,如果执行成功则隐式的提交事务,如果执行失败则隐式的回滚事务。事务管理,是一组相关的操作处于一个事务之中,因此必须关闭数据库的自动提交模式。这点,Spring会在org/springframework/jdbc/datasource/DataSourceTransactionManager.java中将底层连接的自动提交特性设置为false。”

 

那么问题来了,为什么autocommit设置为false就可以使用事务了呢?先把结论讲一下,就是在autocommit=off的情况下,可以将未commit的sql语句(其执行结果存储在缓存中的)回滚rollback掉。

当autocommit=on的情况下,是无法回滚的(注意:myisam引擎是无法使用事务的)

 

set names utf8;
create table t(a int, primary key (a))engine=innodb;
select @@autocommit;
set autocommit=off;
show variables like 'autocommit%';
insert into t(a)values(20);
insert into t(a)values(21);
insert into t(a)values(22);
rollback;

则执行的三条语句全部都会回滚掉。而如果

set names utf8;
create table t(a int, primary key (a))engine=innodb;
select @@autocommit;
set autocommit=off;
show variables like 'autocommit%';
insert into t(a)values(20);
commit;
insert into t(a)values(21);
insert into t(a)values(22);
rollback;

则执行的后两条语句会回滚掉

 

那么spring@Transactional来修饰一个方法时,将mysql的底层事务进行了抽象,总结起来就做了两件事:

1. 将autocommit=off,为回滚做准备

2. 在方法执行过程中如果报错,执行rollback,否则执行commit

再回到最初的那个问题,如何判断spring @Transactional是否成功了呢?

那么可以在第一条sql语句执行完成后打breakpoint,如果查询事务中在RC或RR级别下查不出,那么说明在执行事务;

而如果可以查出,说明autocommit仍为on的状态,没有在执行事务

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值