您好,欢迎来到锐游网。
搜索
您的当前位置:首页Spring事务-代理模式导致事务不回滚问题分析

Spring事务-代理模式导致事务不回滚问题分析

来源:锐游网

说明

  首先我们都了解事务为什么回滚,回滚的原因是什么。默认情况下,事务只有遇到运行期异常时才会回滚,而在遇到检查型异常时不会回滚。

问题描述

我们定义两个类,一个类中有两个事务方法,如图:

package com.helu.samui.service;

import com.helu.samui.dao.UserInfoDao;
import com.helu.samui.entity.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service(value = "userInfoService")
public class UserInfoService {

    @Autowired
    private UserInfoDao userInfoDao;
    @Autowired
    private TestService testService;

    @Transactional
    public void save() {
        userInfoDao.insert(getUserInfo("a1"));
        try {

            //内部类调用不会触发代理模式
            this.test();
            //testService.test();
        } catch (Exception e) {
            System.out.println("aaaaaaaaaaaaaaa");
            e.printStackTrace();
        }
        userInfoDao.insert(getUserInfo("a2"));
    }

    @Transactional
    public void test() {
        throw new RuntimeException();
    }

    private UserInfo getUserInfo(String loginName) {
        UserInfo userInfo = new UserInfo();
        userInfo.setLoginName(loginName);
        return userInfo;
    }
}

如图: save()方法上加了@Transactional注解,表示开启了一个事务,在其中进行了两次插入操作,中间调用this.test()这个同一个类中方法,我们可以发现在代码执行到save()的时候,异常被捕获,事务未被回滚。
输出:

开始测试-----------------
catch the exception.
测试结束-----------------

数据库: 插入两条数据

package com.helu.samui.service;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service(value = "testService")
public class TestService {

    @Transactional
    public void test() {
        throw new RuntimeException();
    }
}

我们再来看下输出和数据库的情况:
输出:

分析

  我们从日志着手,首先,同样异常都被捕获住了,但是调用其他类中的事务方法的时候多抛出了一个异常,UnexpectedRollbackException,并且提示事务被回滚,因为rollback-only已经被标记成需要回滚了,那我们就根据异常一步一步分析吧。
  我们已经知道回滚标记已经被置成true,异常是testService中抛出,我们看看为什么回滚标记,什么时候被置为true的。首先,事务的实现是基于代理模式实现,当调用testService中的test方法的时候触发了代理模式,而直接调用this.test(),因为this是被真实对象本身,所以并不会触发代理模式,这就是这两者区别的真正原因。

源码分析可以参照:http://www.cnblogs.com/chihirotan/p/6739748.html

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- ryyc.cn 版权所有 湘ICP备2023022495号-3

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务