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("第二个事务#############");
}
}