内容简介:Spring核心系列之Spring中的事务
Hello,大家好,前面两篇文章给大家分享了Spring AOP,今天就趁热打铁,给大家分享一下,Spring中的事务,事务这个事,其实在国内一些小公司,一般都会忽略的,尤其是很多网站,设计不到钱的系统,不会在乎这个东西,事务不回滚造成的结果无非就是脏数据,脏改等后果。因为作者以前待过的一个房产网站,根本就不在乎这个事务,有问题就有问题了,反正用户也没充钱在网站上。呵呵。今天还是和大家分享一下这个Spring的事务,因为这个东西算是Spring 内部使用AOP最好的一个体现,体现了AOP思想,OK,文章结构:
- Spring boot 中的事务
- Spring事务中的事务属性
1. Spring boot 中的事务
看到Spring boot,很多人肯定感觉是被忽悠了,为什么说讲Spring事务,这又来Spring boot搞事情。用过Spring boot的小伙伴其实都知道,这两个没什么大的区别,笔者这里使用Spring boot来演示,完全是为什么了简便。因为搭一个Spring传统的ssm三件套工程可能要花费5分钟,而搭建一个Spring boot的"ssm"工程,就是鼠标点一点的事。而且开启事务也是一个注解的事。所以,老铁们,对不住了,这一篇用Spring boot和大家演示Spring的事务,这里我给一个传送门,是传统项目的事务,大家可以参考下:
废话说下,直接上Spring boot代码:
@SpringBootApplication @EnableTransactionManagement public class TestTxApplication { public static void main(String[] args) { SpringApplication.run(TestTxApplication.class, args); } }
@EnableTransactionManagement 表示开启事务!
@Component public class PersonService { @Autowired private PersonMapper personMapper; @Transactional public void testTx(){ //该操作会成功 personMapper.update(); //该操作会报异常 personMapper.update2(); } }
这是一个Service,内部的personMapper是一个dao接口,持久化用的mybatis
@Mapper public interface PersonMapper { //更改某条记录 @Update("update user_info set user_name='123' where user_id='1' ") Long update(); //user_info2这个表不存在。会报异常 @Update("update user_info2 set user_name='123' where user_id='1' ") Long update2(); }
演示的效果应该是:
- 当调用PersonService的testTx()时,由于开启了事务,所以update2报异常时,应该会回滚。update1的操作不会被写入数据库。
- 去掉testTx()上面的@Transactional注解,再做试验,发现虽然报异常,但数据还是update了。
具体我就不演示了 。大家可以看到,在Spring boot中开启事务就是一个注解的事 。具体的内部使用什么trancationManagement根本不用管,Spring boot内部会根据pom中引入的持久层框架自动注入。真是开发神器!
然后我说下底层原理: Spring事务其实就是Spring AOP,底层创建动态代理对象,在代码的开头结尾封装了开启事务和事务回滚操作 。用过JDBC原生代码的更应该清楚了,都是显示在代理里commit和rollback的。然后一大堆try catch..
2. Spring事务中的事务属性
上面的代码虽然简单,也能应对大部分的场景,但还是有一些问题的,比如,有些异常开发者知道,并且想人为的控制,"抛出某类异常,不要回滚".这样的问题。这就引出了, 事务属性 这个概念, 事务属性通常由事务的传播行为,事务的隔离级别,事务的超时值和事务只读标志组成 。 这些属性都是在使用@Transactional可以指定的,我给一张表格:
然后把这些属性讲一讲:
2.1 isolation
事务的隔离界别:使用@Transactional的Isolation属性可以指定事务的隔离级别。但事务的隔离级别是由底层的数据库实现的,并不是由Spring来实现。
- ISOLATION_DEFAULT ,这是默认的隔离级别,使用数据库默认的事务隔离级别.另外四个与JDBC的隔离级别相对应.
- ISOLATION_READ_UNCOMMITTED 这是事务最低的隔离级别,它充许别外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。
- ISOLATION_READ_COMMITTED 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。
- ISOLATION_REPEATABLE_READ 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了不可重复读。
- ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。
一般的数据库默认提供的是READ_COMMITTED隔离级别,如sqlserver2000;Mysql默认提供的是REPEATABLE_READ;
好了,结论给大家说完了,然后解释一下上面提到的 脏读,不可重复读和幻象读的概念。
脏读:
- Mary的原工资为1000,财务人员将Mary的工资改为了8000,但未提交事务
- 与此同时,Mary正在读取自己的工资.Mary发现自己的工资变为了8000,欢天喜地! (脏读)
- 而财务发现操作有误,而回滚了事务,Mary的工资又变为了1000.
不可重复读: 在一个事务中前后两次读取的结果并不致,导致了不可重复读。
- 在事务1中,Mary 读取了自己的工资为1000,操作并没有完成 .
- 在事务2中,这时财务人员修改了Mary的工资为2000,并提交了事务.
- 在事务1中,Mary 再次读取自己的工资时,工资变为了2000.
幻想读:
- 目前工资为1000的员工有10人。
- 事务1,读取所有工资为1000的员工。共读取10条记录 .
- 这时另一个事务向employee表插入了一条员工记录,工资也为1000
- 事务1再次读取所有工资为1000的员工,共读取到了11条记录,这就产生了幻像读。
好了,事务的隔离级别就讲完了,一般还是采用数据库默认的,像 mysql 的REPEATABLE_READ,能够避免脏读和不可重复读。
2.2 propagation
- REQUIRED:表示业务方法需要在一个事务中处理,如果业务方法执行时已经在一个事务中,则加入该事务,否则重新开启一个事务。这也是默认的事务传播行为;
- NOT_SUPPORTED:声明业务方法不需要事务,如果业务方法执行时已经在一个事务中,则事务被挂起,等方法执行完毕后,事务恢复进行;
其他的传播行为省略,基本不用,一般的传播行为也是使用默认的:REQUIRED
2.3 rollbackFor rollbackForClassName noRollbackFor norollbackForClassName
Transactional的异常控制,默认是Check Exception不回滚,unCheck Exception回滚,rollbackFor 和noRollbackFor 配置也许不会含盖所有异常,对于遗漏的按照Check Exception 不回滚,unCheck Exception回滚.
使用@Transactional注解的noRollbackFor和rollbackFor属性可以改变默认的行为:
- 如:@Transactional(rollbackFor=Exception.class)可以使checked异常发生时,数据库操作也rollback,@Transactional(noRollbackFor=RuntimeException.class)可以使unchecked异常发生时也提交数据库操作。
也可以使用noRollbackForClassName、rollbackForClassName属性来指定一个异常类名的String数组来改变默认的行为。
好了,事务属性大致就这么多了,其他一些就是比较简单的了,看名字就知道啥意思,伸手就用的东西,然后再提一下,@Transactional只能被应用到public方法上, 对于其它非public的方法,如果标记了@Transactional也不会报错,但方法没有事务功能..
老实说,一般事务属性配置的比较少,一般都是直接@Transactional加上就完事了。很少配置一些属性。尤其是那个事务传播行为,在日常的业务里,很少有食物嵌套的情况,所以我就是点了一点,没有展开。一般使用默认就可以了。
结语
好了,Spring的事务使用层面给大家算是分享完了,在Spring boot里想使用事务简单的有点可怕。所以我就采用Spring boot了。其实传统的SSM项目也很简单,无非就是在xml文件里配置下tranclationManagement..然后Spring 事务的底层是Spring AOP,把jdbc的事务代码嵌入了进去。 Over,Have a good day!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Java事务解析(事务的基本操作+隔离的等级+事务的四大特性+事务的概念)
- 在云中管理事务,第 1 部分: 事务基础和分布式事务
- Spring事务专题(三)事务的基本概念,Mysql事务处理原理
- 嵌套事务、挂起事务,Spring 是怎样给事务又实现传播特性的?
- 分布式事务中使用RocketMQ的事务消息机制优化事务的处理逻辑
- 数据库事务与事务的隔离级别
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。