欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring注解式事务失效问题记录

程序员文章站 2022-05-31 11:46:28
...

Spring注解式事务失效问题记录


进入甲方弘康人寿后,搭建保全中心时,遇到的一个问题,同一个类中的一个事务方法调用另一个事务时,第二个事务会失效的问题

本文此次仅仅做个记录,这段时间忙完之后再好好梳理下事务这块。spring事物是基于类和接口的所以只能在类里面调用另一个类里面的事物,同一个类里面调用自己类的事物方法是无效的。

 *     spring事物也不要频繁使用,在事物处理的同时操作的第一张表会被限制查看的(即被临时锁住)。数据量大的时候会有一定影响。
 *     解决方法
 *     1.在新增类中调用事务
 *     2.用AopContext代理调用  ps: ((TestTransactional)AopContext.currentProxy()).add1();
 */
本类中的一个事务方法调用第二个事务方法时,第二个事务会失效
package com.huida.investment.controller;

import com.huida.investment.entity.LdcodeEntity;
import com.huida.investment.service.base.LdcodeService;
import org.apache.catalina.core.ApplicationContext;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * @description: 事务demo
 *
1.propagation-required: 支持当前事务,如果有就加入当前事务中;如果当前方法没有事务,就新建一个事务;
2.propagation-supports: 支持当前事务,如果有就加入当前事务中;如果当前方法没有事务,就以非事务的方式执行;
3.propagation-mandatory: 支持当前事务,如果有就加入当前事务中;如果当前没有事务,就抛出异常;
4.propagation-requires_new: 新建事务,如果当前存在事务,就把当前事务挂起;如果当前方法没有事务,就新建事务;
5.propagation-not-supported: 以非事务方式执行,如果当前方法存在事务就挂起当前事务;如果当前方法不存在事务,就以非事务方式执行;
6.propagation-never: 以非事务方式执行,如果当前方法存在事务就抛出异常;如果当前方法不存在事务,就以非事务方式执行;
7.propagation-nested: 如果当前方法有事务,则在嵌套事务内执行;如果当前方法没有事务,则与required操作类似;

 * @author: zhanghailang
 * @date: 2020-10-14 14:54
 */
@RestController
public class TestTransactional {
    @Autowired
    LdcodeService ldcodeService;
    @Autowired
    TestTransational2 testTransational2;
    @GetMapping(value = "/get1")
    @Transactional(rollbackFor = Exception.class)
    public String add() throws InterruptedException {
        LdcodeEntity ldcodeEntity = new LdcodeEntity();
        ldcodeEntity.setCodename("事务demo");
        ldcodeEntity.setCodetype("TestTrans9");
        ldcodeEntity.setCode("test129");
        ldcodeService.save(ldcodeEntity);
        List<String> list = ldcodeService.queryTLRiskCode();



//        //本类中新的事务
          //catch 住新事务的异常
//        try {
//            add1();
//        }catch (Exception e){
//            System.out.println("第二个事务的异常被catch");
//        }
//        Thread.sleep(20000);
//        System.out.println("事务结束");

        //使用代理的方式获取本类中第二个事务方法
        ((TestTransactional)AopContext.currentProxy()).add1();


        //从另一个类中调用第二个事物的方法
//        testTransational2.add1();
        throw new RuntimeException("1111");
//        return list.get(1);
    }
    /**
     *     spring事物是基于类和接口的所以只能在类里面调用另一个类里面的事物,同一个类里面调用自己类的事物方法是无效的。
     *     spring事物也不要频繁使用,在事物处理的同时操作的第一张表会被限制查看的(即被临时锁住)。数据量大的时候会有一定影响。
     *     解决方法
     *     1.在新增类中调用事务
     *     2.用AopContext代理调用  ps: ((TestTransactional)AopContext.currentProxy()).add1();
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class)
    public void add1() {
        //本类中的第二个事务不会生效,无论事务隔离级别是哪种  原因是aop的动态代理

        //TODO
        //如果希望第二个事务可以提前提交,第一个事务回滚时还可以将第二个事务回滚  ?????
        System.out.println("本类中的第二个事务");

        LdcodeEntity ldcodeEntity = new LdcodeEntity();
        ldcodeEntity.setCodename("事务demo");
        ldcodeEntity.setCodetype("NewTestTrans9");
        ldcodeEntity.setCode("ntest139");
        ldcodeService.save(ldcodeEntity);


//        throw new RuntimeException("1111");
        System.out.println("第二个事务#############");
        }

}

将第二个事务方法添加到新增类中,事务才会生效

package com.huida.investment.controller;

import com.huida.investment.entity.LdcodeEntity;
import com.huida.investment.service.base.LdcodeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @description: 第二个事务服务类
 * @author: zhanghailang
 * @date: 2020-10-14 16:07
 */
@Component
public class TestTransational2 {
    @Autowired
    LdcodeService ldcodeService ;
    @Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class)
    public void add1() {
        System.out.println("这是另一个类中的第二个事务");
        LdcodeEntity ldcodeEntity = new LdcodeEntity();
        ldcodeEntity.setCodename("事务demo");
        ldcodeEntity.setCodetype("NewTestTrans8");
        ldcodeEntity.setCode("ntest138");
        ldcodeService.save(ldcodeEntity);
//        throw new RuntimeException("1111");
        System.out.println("第二个事务#############");
    }
}
相关标签: 经历 java aop