@Transactional

2020-11-29

java

事者,生于虑,成于务,失于傲。——管仲

如果想让该类或方法被事务支持,则可以加上@Transactional注解

@Transactional有几个参数:

value/transactionManager——是用来指定事务管理器,这个不太常用

timeout——事务超时时间,为传播特性为PROPAGATION_REQUIRES_NEWPROPAGATION_REQUIRED定制,创建新事务时旧事务的超时时间,出场率也不是特别高

下面的则是常用的参数

readOnly——是否为只读事务,如果为true时,进行查询操作效率会更高,但不能进行除查询外的操作,会报错

rollbackFor/rollbackForClassName——指定需要回滚的异常

noRollbackFor/noRollbackForClassName——指定不需要回滚的异常

默认对编译异常不会滚

对非受检异常回滚,例如RuntimeException就会回滚事务

isolation——配置隔离级别

事务丢失

回滚丢失——另一个事务回滚导致当前事务丢失

覆盖丢失——另一个事务提交导致当前事务丢失

org.springframework.transaction.annotation.Isolation枚举类下面有这样几种
DEFAULT——使用你JDBC默认的隔离级别
Read uncommitted脏读——当前事务能读到另一个事务执行后还未提交的数据

事务A读取了事务B中尚未提交的数据。如果事务B回滚,则A读取使用了错误的数据

例如AB同时执行,B执行了SQL还没提交事务,A查询时看到了当前数据为B刚刚修改的,这个时候如果B回滚了,则A使用了错误数据

Read committed会产生不可重复读——当前事务能读到另一个事务提交修改后的数据

不可重复读是指在对于数据库中的某个数据,一个事务范围内多次查询却返回了不同的数据值,这是由于在查询间隔,被另一个事务修改并提交了。

例如AB同时执行,A查询到B提交前的数据,B执行了修改SQL提交了事务以后,A再查询能看到B修改后的结果

但对新增和删除仍然和脏读一样,能看到新增/删除后未提交事务的数据

Repeatable read会产生幻读——当前事务能读到另一个事务提交新增/删除后的数据

在事务A多次读取构成中,事务B对数据进行了新增操作,导致事务A多次读取的数据不一致。

例如AB同时执行,A能读取到 B执行了新增/删除SQL并提交了事务后的数据

Serializable避免发生以上事务丢失、脏读、幻读、不可重复读情况,性能低下

propagation——配置事务传播特性

例如在一个service调用另一个service中的方法时,需要配置

注意,如果是同一个service下,如果需要事务支持,需要注入它本身,然后再调用注入的service执行方法,否则会导致事务生效,因为调用方法需要经过spring容器管理

例如:A调用BB配置下列传播特性后

无事务:

PROPAGATION_NEVER——如果A有事务则抛异常(导致项目启动失败)
PROPAGATION_NOT_SUPPORTED——如果A没事务,B也没有。如果有则挂起A的事务,B无事务执行后A事务继续生效

有则用,无则不用:

PROPAGATION_SUPPORTS——如果A没有事务,则B也无事务,有事务则BA的事务

有事务:

PROPAGATION_REQUIRES_NEW——如果A没有事务则创建一个B的,如果A有事务,挂起A的事务,B创建事务结束后A继续生效,不被B影响
PROPAGATION_NESTED——如果A没事务则创建一个B的,有事务则嵌套事务,B出异常不影响AA出异常会回滚B
PROPAGATION_REQUIRED——默认,如果A没有事务则创建事务,有则用A的事务
PROPAGATION_MANDATORY——如果A没有事务,抛出异常(导致项目启动失败),有则用A的事务