Spring事务问题

2019-01-02  本文已影响5人  Tomy_Jx_Li

问题:Spring中存在类A和类B,A中存在方法methodA。B中存在方法methodB1和methodB2。methodB1上不存在Transactional事务管理,也就是没有注解@Transactional。methodB2上存在注解@Transactional。那么方法A调用methodB1,methodB1又调用methodB2。这时如果methodB2抛出异常了。那么事务会回滚吗???

问题复现,代码如下

StudentCtrl

package com.jiyx.test.testspringbootmybatis.ctrl;

import com.jiyx.test.testspringbootmybatis.entity.Student;
import com.jiyx.test.testspringbootmybatis.service.StudentSV;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * auther: jiyx
 * date: 2018-12-26.
 */
@RestController
@RequestMapping("/student")
public class SutdentCtrl {

    @Autowired
    private StudentSV studentSV;

    @GetMapping("/hello")
    public String hello() {
        return "hello";
    }

    @GetMapping("/findAll")
    public List<Student> findALl() {
        return studentSV.findAll();
    }

    @PostMapping("/add")
    public void insert(@RequestBody Student student) {
        studentSV.insert(student);
    }
}

StudentSV

package com.jiyx.test.testspringbootmybatis.service;


import com.jiyx.test.testspringbootmybatis.entity.Student;

import java.util.List;

/**
 * auther: jiyx
 * date: 2018-12-26.
 */
public interface StudentSV {

    List<Student> findAll();

    void insert(Student student);

    void insert1(Student student);
}

StudentSVImpl是StudentSV的实现类

package com.jiyx.test.testspringbootmybatis.service.impl;

import com.jiyx.test.testspringbootmybatis.entity.Student;
import com.jiyx.test.testspringbootmybatis.mapper.StudentExample;
import com.jiyx.test.testspringbootmybatis.mapper.StudentMapper;
import com.jiyx.test.testspringbootmybatis.service.StudentSV;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * auther: jiyx
 * date: 2018-12-26.
 */
@Service("studentSV")
public class StudentSVImpl implements StudentSV {

    @Autowired
    private StudentMapper studentMapper;

    @Override
    public List<Student> findAll() {
        return studentMapper.selectByExample(new StudentExample());
    }

    @Override
//    @Transactional(rollbackFor = RuntimeException.class)
    public void insert(Student student) {
        this.insert1(student);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void insert1(Student student) {
        studentMapper.insert(student);
        throw new RuntimeException("回滚吗?");
    }
    
}

结论:

经测试,方法调用链是A->B1->B2的时候,是不能够产生管理事务的,所以就算抛出异常也不能回滚。

原因:

因为spring的事务调用是基于AOP的,而同一个类中的方法调用是不会走aop的。具体原因可以查看源码。推荐一个博客吧

解决方法:

方式一:在B1上直接加上注解@Transactional
方式二:在启动类上,加上配置@EnableAspectJAutoProxy(exposeProxy = true),然后再B1中使用(StudentSV)AopContext.currentProxy()进行调用。
方式二如图:


启动类注解配置
B1修改
上一篇 下一篇

猜你喜欢

热点阅读