就同一个Service类中,一个方法调用另外一个有事务的方法的思考
写这篇博客的缘由:
我在Spring事务管理嵌套事务详解 : 同一个类中,一个方法调用另外一个有事务的方法——levae1024.评论过,有人说我杠,这里就写篇实际操作的博客证明下我的评论
现在库里的数据如下图所示:
现在我在同一个Service中一个事务的方法调用另外一个事务方法:
目的是 将id为1与2 的记录中的name属性值Jack与Rose 分别改为Tom与Jerry
如下图代码所示:
package com.wqf.service.flowable.impl;
import com.wqf.dao.flowable.FlowableStudentMapper;
import com.wqf.entity.Student;
import com.wqf.service.flowable.FlowableStudentService;
import com.wqf.service.mybatis.MybatisStudentService;
import com.wqf.util.Constants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
/**
* @Author: Wang Qifan
* @Date: 2020/5/24 22:58
* @Description:
*/
@Service
@Transactional(value = Constants.FLOWABLE_TM)
public class FlowableStudentServiceImpl implements FlowableStudentService {
@Resource
private FlowableStudentMapper flowableStudentMapper;
@Autowired
private MybatisStudentService mybatisStudentService;
//注入自己
@Autowired
private FlowableStudentService flowableStudentService;
@Transactional
public void updateStudent(Student student) {
student = new Student();
student.setId(1);
student.setStudentId(3);
student.setName("Tom");
System.out.println("first查询1:" + flowableStudentMapper.getStudentById(1));
System.out.println("first查询2:" + flowableStudentMapper.getStudentById(2));
flowableStudentMapper.updateStudentById(student);
try {
flowableStudentService.updateOtherStudent(null);
}catch (Exception e){
//这里用的try catch 吃掉addOtherStudent()的异常,
//避免了因为addOtherStudent()抛出的异常 而导致此updateStudent()方法异常,从而导致回滚
System.out.println("消化addOtherStudent()的异常");
}
System.out.println("second查询1:" + flowableStudentMapper.getStudentById(1));
System.out.println("second查询2:" + flowableStudentMapper.getStudentById(2));
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateOtherStudent(Student student) {
student = new Student();
student.setId(2);
student.setStudentId(3);
student.setName("Jerry");
flowableStudentMapper.updateStudentById(student);
//模拟运行时异常,这个肯定会回滚
int a = 1/0;
}
@Override
public Student getStudentById(int id) {
Student student = flowableStudentMapper.getStudentById(id);
return student;
}
}
调用测试类:
package com.wqf;
import com.wqf.service.flowable.FlowableStudentService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
* Author: Wang Qifan
* Date: 2021/2/22 15:56
* Description:
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class PropagationRequiresNewTest {
@Autowired
private FlowableStudentService flowableStudentService;
@Test
public void test(){
System.out.println("first查询1:" + flowableStudentService.getStudentById(1));
System.out.println("first查询2:" + flowableStudentService.getStudentById(2));
flowableStudentService.updateStudent(null);
System.out.println("second查询1:" + flowableStudentService.getStudentById(1));
System.out.println("second查询2:" + flowableStudentService.getStudentById(2));
}
}
结果如下图所示:
分析:这里若是updateStudent()方法和updateOtherStudent()是同一个事务,那么肯定是同时回滚(因为我上面人为得写了一个运行时异常),而实际结果是updateOtherStudent()回滚了,而updateStudent()中得成功了,那么显然易见,他们不是同一个事务。
若是直接调用:
id为1的改为Mary
他们是同一个事务,读者可自行验证