二十二、spring 事务之踩过的坑

2018-07-20  本文已影响0人  xiaoming_he

这节主要记录我在使用Spring事务过程中遇到过的坑。

没有抛出异常

@Transactional
public void addUser(User user) {
    try {
        userMapper.addUser(user);
        int i = 1/0;
    } catch (Exception e) {
        e.printStackTrace();
    }
}

上面代码user是能够添加成功的,因为不抛出异常,spring是没有办法捕获的,所以就不能执行回滚。

this调用声明REQUIRES_NEW的事务,是不会重新创建事务的

@Transactional
public void addUser(User user) {
    this.update();
}

@Transactional(propagation = REQUIRES_NEW)
public void update() {

}

update()方法不会重新创建一个事务的,因为this指向的是目标方法,而要使用事务必须使用代理对象才能生效。为了解决这个问题,可以通过下面方式:

@EnableAspectJAutoProxy(exposeProxy = true)

然后将this.update()修改为:

((UserService)AopContext.currentProxy()).update();

AopContext.currentProxy()是在创建代理的时候,通过下面代码赋值的

if (this.advised.exposeProxy) {
    // Make invocation available if necessary.
    oldProxy = AopContext.setCurrentProxy(proxy);
    setProxyContext = true;
}

Transaction rolled back because it has been marked as rollback-only异常

这个是一个同事问我,他想做的是在a方法中调用b方法,但是b失败,不影响a的事务,代码如下:

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private EmployeeService employeeService;

    @Transactional
    public void addUser(User user) {
        userMapper.addUser(user);
        try {
            employeeService.addEmployee();
        } catch (Exception e) {
            //e.printStackTrace();
        }
    }
}
@Service
public class EmployeeService {

    @Transactional
    public void addEmployee() {
        int i = 1/0;
    }
}

这个是因为在addEmployee中抛出异常时,在回滚时如果不是一个新的事务就会把事务状态设置成readOnly,但是在addUser中又没有把异常抛出,所以会提交事务,在提交的时候就会校验事务是否设置成readOnly,就抛出UnexpectedRollbackException异常。解决办法就是让addEmployee新启一个事务@Transactional(propagation = Propagation.REQUIRES_NEW)

上一篇下一篇

猜你喜欢

热点阅读