mysql事务注解_事务(@Transactional注解)的用法和实例

本文详细介绍了MySQL中@Transactional注解的使用,包括参数如isolation(事务隔离级别)、propagation(事务传播机制)、readOnly等。讲解了不同隔离级别和传播机制的含义,以及如何配置事务的回滚和不回滚条件。强调了@Transactional应在具体方法上使用,并注意只有在抛出未被捕获的RuntimeException时Spring才会自动回滚事务。
摘要由CSDN通过智能技术生成

2ff34e647e2e3cdfd8dca593e17d9b0a.png

参数

@Transactional可以配制那些参数及以其所代表的意义:参数意义isolation事务隔离级别

propagation事务传播机制

readOnly事务读写性

noRollbackFor一组异常类,遇到时不回滚。默认为{}。

noRollbackForClassName一组异常类名,遇到时不回滚,默认为{}

rollbackFor一组异常类,遇到时回滚

rollbackForClassName一组异常类名,遇到时回滚

timeout超时时间,以秒为单位

value可选的限定描述符,指定使用的事务管理器

isolation

isolation属性可配置的值有:Isolation.READ_COMMITTED :使用各个数据库默认的隔离级别

Isolation.READ_UNCOMMITTED :读未提交数据(会出现脏读,不可重复读,幻读)

Isolation.READ_COMMITTED :读已提交的数据(会出现不可重复读,幻读)

Isolation.REPEATABLE_READ :可重复读(会出现幻读)

Isolation.SERIALIZABLE :串行化数据库默认隔离级别MYSQL: 默认为REPEATABLE_READ级别

SQLSERVER: 默认为READ_COMMITTED

Oracle 默认隔离级别 READ_COMMITTED

propagation

propagation属性可配置的值有:传播机制说明Propagation.REQUIRED如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是 最常见的选择,也是Spring的默认传播机制。

Propagation.SUPPORTS支持当前事务,如果当前没有事务,就以非事务方式执行。

Propagation.MANDATORY使用当前的事务,如果当前没有事务,就抛出异常。

Propagation.REQUIRES_NEW新建事务,如果当前存在事务,把当前事务挂起。

Propagation.NOT_SUPPORTED以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

Propagation.NEVER以非事务方式执行,如果当前存在事务,则抛出异常。

Propagation.NESTED如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与 PROPAGATION_REQUIRED 类似的操作。

上一篇写事务的文章中已经把这两个属性说得很清楚了,这里就不再赘述了。

readOnly

默认情况下是false,可以显示指定为true, 告诉程序该方法下使用的是只读操作,如果进行其他非读操作,则会跑出异常;概念:

从这一点设置的时间点开始(时间点a)到这个事务结束的过程中,其他事务所提交的数据,该事务将看不见!(查询中不会出现别人在时间点a之后提交的数据)

应用场合:

如果你一次执行单条查询语句,则没有必要启用事务支持,数据库默认支持SQL执行期间的读一致性;

如果你一次执行多条查询语句,例如统计查询,报表查询,在这种场景下,多条查询SQL必须保证整体的读一致性,否则,在前条SQL查询之后,后条SQL查询之前,数据被其他用户改变,则该次整体的统计查询将会出现读数据不一致的状态,此时,应该启用事务支持。

【注意是一次执行多次查询来统计某些信息,这时为了保证数据整体的一致性,要用只读事务】

rollbackForClassName/rollbackFor

Spring默认情况下会对运行期例外(RunTimeException)进行事务回滚。这个例外是unchecked,如果遇到checked意外就不回滚。

用来指明回滚的条件是哪些异常类或者异常类名。

noRollbackForClassName/noRollbackFor

用来指明不回滚的条件是哪些异常类或者异常类名。

timeout

用于设置事务处理的时间长度,阻止可能出现的长时间的阻塞系统或者占用系统资源。单位为秒。如果超时设置事务回滚,并抛出TransactionTimedOutException异常。

value

value这里主要用来指定不同的事务管理器;主要用来满足在同一个系统中,存在不同的事务管理器。

比如在Spring中,声明了两种事务管理器txManager1, txManager2.然后,用户可以根据这个参数来根据需要指定特定的txManager.存在多个事务管理器的情况: 在一个系统中,需要访问多个数据源,则必然会配置多个事务管理器。

注意点不要在接口上使用注解,可能会无效,要在实现类的具体方法上写。

可以在类级别上使用注释,但是会使类下的所有方法都有事务,影响效率。

只能对public方法使用事务,@Transactional注解的方法都是被外部其他类调用才有效,故只能是public。

[email protected],对同一个类里面的方法调用, @Transactional无效。比如有一个类Test,它的一个方法A,A再调用Test本类的方法B(不管B是否public还是private),但A没有声明注解事务,而B有。则外部调用A之后,B的事务是不会起作用的。

不回滚的情况

spring事务机制:默认spring事务只在发生未被捕获的RuntimeException时才回滚。

spring aop异常捕获原理:被拦截的方法需要显式抛出异常,不能经过处理,这样aop代理才能捕获到方法的异常,才能进行回滚。

默认情况下aop只捕获RuntimeException的异常,但可以通过配置来捕获特定的异常并回滚。换句话说,在service的方法中不使用try-catch或者在catch中最后加上throw new RuntimeException(),这样程序发生异常时才能被aop捕获进而回滚。

解决方案:例如Service层处理事务,那么Service中的方法中不做异常捕获,或者在catch语句中最后增加throw new RuntimeException()语句,以便aop捕获异常再去回滚,并且在service上层要继续捕获这个异常并处理。

在service层方法的catch语句中增加:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();语句,手动回滚,这样上层就无需去处理异常。

SQLException本身是受检查的异常,但是在Spring框架下,抛出的是org.springframework.dao包中的异常,都是RuntimeException的子类,这是有关数据库的异常会回滚的原因。

例子

不想写了…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值