首先我们都了解事务为什么回滚,回滚的原因是什么。默认情况下,事务只有遇到运行期异常时才会回滚,而在遇到检查型异常时不会回滚。
我们定义两个类,一个类中有两个事务方法,如图:
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
本站由北京市万商天勤律师事务所王兴未律师提供法律服务