@Transactional 同一个类中无事务方法a()内部调用有事务方法b()的问题

@Transactional 同一个类中无事务方法a()内部调用有事务方法b()的问题
原创袁义锐 最后发布于2019-05-13 17:32:49 阅读数 2269  收藏
展开
1. 事务的4种特性        

序号    参数    含义
1    原子性(Atomicity)    事务是数据库的逻辑工作单位,它对数据库的修改要么全部执行,要么全部不执行。
2    一致性(Consistemcy)    事务前后,数据库的状态都满足所有的完整性约束。
3    隔离性(Isolation)    并发执行的事务是隔离的,一个不影响一个。通过设置数据库的隔离级别,可以达到不同的隔离效果
4    持久性(Durability)    在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。
2.Transactional()控制事务传播的配置项目(默认Propagation.REQUIRED)

    @Transactional(propagation=Propagation.REQUIRED)           //控制事务传播。默认是Propagation.REQUIRED
    @Transactional(isolation=Isolation.DEFAULT)                //控制事务隔离级别。默认跟数据库的隔离级别相同
    @Transactional(readOnly=false)                             //控制事务可读写、只可读。默认可读写
    @Transactional(timeout=30)                                 //控制事务的超时时间,单位秒。默认跟数据库的事务控制系统相同
    @Transactional(rollbackFor=RuntimeException.class)         //控制事务遇到哪些异常会回滚。默认是RuntimeException
    @Transactional(rollbackForClassName=RuntimeException)      //同上
    @Transactional(noRollbackFor=NullPointerException.class)   //控制事务遇到哪些异常不会回滚。默认遇到RuntimeException回滚
    @Transactional(noRollbackForClassName=NullPointerException)//同上
3.事务的7中传播特性4. 事务的传播案例:

序号    传播行为    含义
1    REQUIRED    如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。
2    SUPPORTS    如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行
3    MANDATORY    如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。
4    NESTED    如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务,则按REQUIRED属性执行
5    NEVER    总是非事务地执行,如果存在一个活动事务,则抛出异常
6    REQUIRES_NEW    总是开启一个新的事务。如果一个事务已经存在,则将这个已经存在的事务挂起
7    NOT_SUPPORTED    总是非事务地执行,并挂起任何存在的事务
4.举个上手的按例:事务在A类的a()方法中调用B类的b()方法的传播案例

 

A.a()    B.b()的事务配置    a()没有事务的结果    a()有事务的结果
REQUIRED    b()创建自己的事务;    b()接受a()的事务
SUPPORTS    b()不创建自己的事务;    b()接受a()的事务
MANDATORY    b()报异常    b()接受a()的事务
NESTED    b()创建自己的事务;    b()接受a()的事务,成为a()嵌套的子事务
NEVER    b()不创建自己的事务;    b()报异常
REQUIRES_NEW    b()创建自己的事务;    b()不接受a()的事务,b()先执行,内层事务失败不会影响外层事务
NOT_SUPPORTED    b()不创建自己的事务;    b()不接受a()的事务,b()先执行
Java案例:

public class PropagationTest extends BaseServerTest {
 
    private static final Logger logger = Logger.getLogger(PropagationTest.class);
 
 
    @Test
    @Transactional()
    public void a() {
        try {
            PropagationTestB classb = new PropagationTestB();
            classb.b();
        } catch (Exception e) {
            throw new RuntimeException();
        }
    }
}
 
 
class PropagationTestB {
 
    @Autowired
    TRSMapper trsMapper;
 
    @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = false, rollbackFor = RuntimeException.class)
    public void b() {
        try {
            trsMapper.saveNews(new JSONArray());
        } catch (Exception e) {
            throw new RuntimeException();
        }
    }
}
5.特殊案例分析:

Java案例:无事务a()方法中调用同一个类的有事务b()方法问题案例

public class PropagationTest extends BaseServerTest {
 
    private static final Logger logger = Logger.getLogger(PropagationTest.class);
 
    @Autowired
    TRSMapper trsMapper;
 
    @Test
    public void a() {
        try {
            b();
        } catch (Exception e) {
            throw new RuntimeException();
        }
    }
 
    @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = false, rollbackFor = RuntimeException.class)
    public void b() {
        try {
            trsMapper.saveNews(new JSONArray());
        } catch (Exception e) {
            throw new RuntimeException();
        }
    }
}
声明式事务基于Spring AOP实现,将具体业务逻辑与事务处理解耦,在 Spring 的 AOP 代理下,只有目标方法由外部调用,目标方法才由 Spring 生成的代理对象来管理,这会造成自调用问题。

即:

同一类中a()方法没有@Transactional 注解,在其内部调用有@Transactional 注解的方法,有@Transactional 注解的方法b()的事务被忽略,不会发生回滚。
————————————————
版权声明:本文为CSDN博主「袁义锐」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u010235716/article/details/90171802

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当在同一个类方法相互调用时,如果希望事务能够生效,可以采取以下解决办法: 1. 使用代理调用方法:由于Spring事务管理是通过AOP代理实现的,所以可以通过使用代理对象调用方法来触发事务管理。可以通过将方法调用委托给代理对象来确保事务的生效。 2. 将被调用方法抽取到另一个类:将被调用方法抽取到另一个类,并确保在被调用方法上添加@Transactional注解。这样,在调用方法调用被抽取的方法时,事务将能够生效。 3. 使用AspectJ模式的事务管理:Spring还提供了AspectJ模式的事务管理,可以在同一个类方法相互调用时保持事务的生效。通过配置AspectJ的切面来实现事务的管理,可以细粒度地控制事务的传播行为和回滚条件。 需要注意的是,以上解决办法需要根据具体情况选择合适的方式,并确保在调用方法上正确地添加@Transactional注解。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Spring同一个service方法相互调用事务不生效问题解决方案](https://blog.csdn.net/a1036645146/article/details/107469578)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值