Spring事务注意事项 以及 遇到的坑

原创参考:

https://www.cnblogs.com/yougewe/p/7466677.html   (Spring,为内部方法新起一个事务,此处应有坑。)

https://blog.csdn.net/bntx2jsqfehy7/article/details/79040349 (面试必备技能:JDK动态代理给Spring事务埋下的坑!)

spring 事务注意事项:

注意:

  @Transactional 可以作用于接口、接口方法、类以及类方法上。当作用于类上时,该类的所有 public 方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。

  虽然 @Transactional 注解可以作用于接口、接口方法、类以及类方法上,但是 Spring 建议不要在接口或者接口方法上使用该注解,因为这只有在使用基于接口的代理时它才会生效。另外, @Transactional 注解应该只被应用到 public 方法上,这是由 Spring AOP 的本质决定的。如果你在 protected、private 或者默认可见性的方法上使用 @Transactional 注解,这将被忽略,也不会抛出任何异常。

  默认情况下,只有来自外部的方法调用才会被AOP代理捕获,也就是,类内部方法调用本类内部的其他方法并不会引起事务行为,即使被调用方法使用@Transactional注解进行修饰。因为动态代理的原因。

在 SPRING 中一共定义了六种事务传播属性

PROPAGATION_REQUIRED -- 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS -- 支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY -- 支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW -- 新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED -- 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER -- 以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED -- 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。 

最容易弄混淆的其实是PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED 

PROPAGATION_REQUIRES_NEW 启动一个新的, 不依赖于环境的 "内部" 事务. 这个事务将被完全
commited 或 rolled back 而不依赖于外部事务,它拥有自己的隔离范围, 自己的锁, 等等.
当内部事务开始执行时, 外部事务将被挂起, 内务事务结束时, 外部事务将继续执行.
PROPAGATION_REQUIRES_NEW常用于日志记录,或者交易失败仍需要留痕

另一方面, PROPAGATION_NESTED 开始一个 "嵌套的" 事务, 它是已经存在事务的一个真正
的子事务. 潜套事务开始执行时, 它将取得一个 savepoint.
如果这个嵌套事务失败, 我们将回滚到此 savepoint. 潜套事务是外部事务的一部分,
只有外部事务结束后它才会被提交.
由此可见, PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED 的最大区别在于,
PROPAGATION_REQUIRES_NEW 完全是一个新的事务, 而 PROPAGATION_NESTED
则是外部事务的子事务, 如果外部事务 commit, 潜套事务也会被 commit,
这个规则同样适用于 roll back. 

几个例子理解REQUIRED、REQUIRES_NEW、NESTED 的使用注意事项(TRY...CATCH配合使用)

1、REQUIRED的使用注意项

1.1 REQUIRED保证其处理过程同一个事务,如果调用的同一个类的配置的REQUIRED的方法,且此方法存在TRY CATCH
代码块, 如果此代码块出现异常,程序可以继续执行。

1.2 但如果调用的其他类的配置REQUIRED方法,且TRY CATCH住,则全部的提交全部回滚,且报出异常:
Transaction rolled back because it has been marked as rollback-only
因为事务报出异常后要全部回滚,包括父类的调用。

1.3 如果service中包含多个dao的方法,其都属于同一个事务,其中报错全部回滚,try catch住不影响程序代码的继续执行.

class A{
//PROPAGATION_REQUIRED
void methodA() {
try{
methodB(); //可以继续执行,因为是同一个类
}catch(Exception ex){
ex.printStrace();
}

try{
methodC(); //报错Transaction rolled back because it has been marked as rollback-only
//因为回滚整个事务,不能用try catch住.当然通过不会try catch一个事务的部分代码
}catch(Exception ex){
ex.printStrace();
}
}

//PROPAGATION_REQUIRED
void methodB() {

}
}

class B{

//PROPAGATION_REQUIRED
void methodC() {

}
}

2、NESTED的具体用途如下:
在此方法出现异常时,通过TRY CATCH 代码块包含住, 继续往下执行或者执行CATCH中的处理.
此点REUQIRED做不到, REQUIRED_NEW能做到, 但它是单独的事务,不与父类一块提交的。

ServiceA {
/**

* 事务属性配置为 PROPAGATION_REQUIRED

*/

void methodA() {

try {

//savepoint

ServiceB.methodB(); //PROPAGATION_NESTED 级别

} catch (SomeException) {

// 执行其他业务, 如 ServiceC.methodC();
}}}

原文地址:https://www.cnblogs.com/netact/p/10121435.html

时间: 2024-10-28 19:38:37

Spring事务注意事项 以及 遇到的坑的相关文章

Spring事务传播行为中可能的坑点

一.简介 Spring事务配置及相关说明详见:https://www.cnblogs.com/eric-fang/p/11052304.html.这里说明spring事务的几点注意: 1.默认只会检查回滚RuntimeException的异常. 2.@Transactional注解只能作用于public的方法上,默认传播行为 Propagation.REQUIRED 3.service内部方法之间的调用,不会被spring拦截到,也即不会产生事务 二.坑点 主要的坑点就是在嵌套事务上,当serv

[转]@Transactional spring 配置事务 注意事项

@Transactional spring 配置事务 注意事项 [@[email protected]] @Transactional spring 配置事务 注意事项 1. 在需要事务管理的地方加@Transactional 注解.@Transactional 注解可以被应用于接口定义和接口方法.类定义和类的 public 方法上. 2. @Transactional 注解只能应用到 public 可见度的方法上. 如果你在 protected.private 或者 package-visib

@Transactional spring 配置事务 注意事项

http://epine.itpub.net/post/8159/526281 @Transactional spring 配置事务 注意事项 1. 在需要事务管理的地方加@Transactional 注解.@Transactional 注解可以被应用于接口定义和接口方法.类定义和类的 public 方法上. 2. @Transactional 注解只能应用到 public 可见度的方法上. 如果你在 protected.private 或者 package-visible 的方法上使用 @Tr

记一次 Spring 事务配置踩坑记

记一次 Spring 事务配置踩坑记 问题描述:(SpringBoot + MyBatisPlus) 业务逻辑伪代码如下.理论上,插入数据 t1 后,xxService.getXxx() 方法的查询条件会不满足,会查询不到数据.结果事与愿违,后一次的查询,居然查到了数据. void saveXxx(){  xxService.getXxx(); // 查到一条数据 data1  xxService.insert(); // 插入一条数据 t1  xxService.getXxx(); // 查到

Spring事务管理注意小事项

在service类前加上@Transactional,声明这个service所有方法需要事务管理.每一个业务方法开始时都会打开一个事务. Spring默认情况下会对运行期例外(RunTimeException)进行事务回滚.这个例外是unchecked 如果遇到checked意外就不回滚. 如何改变默认规则: 1 让checked例外也回滚:在整个方法前加上 @Transactional(rollbackFor=Exception.class) 2 让unchecked例外不回滚: @Trans

spring事务配置的坑

基于 <tx> 命名空间的声明式事务管理 前面两种声明式事务配置方式奠定了 Spring 声明式事务管理的基石.在此基础上,Spring 2.x 引入了 <tx> 命名空间,结合使用 <aop> 命名空间,带给开发人员配置声明式事务的全新体验,配置变得更加简单和灵活.另外,得益于 <aop> 命名空间的切点表达式支持,声明式事务也变得更加强大. 1.如果没有配置事务,数据库操作是无法成功的. 2. 如果用try catch里的操作是无法用事务管理的? Spr

Spring事务管理----------整合学习版

作者:学无先后 达者为先 Spring提供了一流的事务管理.在Spring中可以支持声明式事务和编程式事务. 一  spring简介 1 Spring的事务       事务管理在应用程序中起着至关重要的作用:它是一系列任务的组成工作单元,在这个工作单元中,所有的任务必须同时执行.它们只有二种可能执行结果,要么所有任务全部执行成功,要么所有任务全部执行失败.     Spring中提供了丰富的事务管理功能,它们超过了EJB并且和EJB一样支持声明式事务,重要的是Spring提供了一致的事务管理,

Spring事务管理-使用注解配置事务

一.概述 事务管理对于企业应用来说是至关重要的,即使出现异常情况,它也可以保证数据的一致性.Spring Framework对事务管理提供了一致的抽象,其特点如下:为不同的事务API提供一致的编程模型,比如JTA(Java Transaction API), JDBC, Hibernate, JPA(Java Persistence API和JDO(Java Data Objects)支持声明式事务管理,特别是基于注解的声明式事务管理,简单易用 提供比其他事务API如JTA更简单的编程式事务管理

spring事务心得积累

一.使用事务 1.spring配置文件中开启事务注解机制 <!-- 开启事务注解机制 --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" > <property name="sessionFactory" ref="sessionFactory&quo