前言
上篇讲到了Spring事务的简单使用,这篇主要描述开发中事务失效场景,以下是本文大纲:
1.异常类型没对应
2.异常被捕捉了
3.方法内部调用
4.方法内部调用事务失效解决方案
异常类型没对应
如下,抛出的Exception大于RuntimeException,是无法回滚的
@Transactional(rollbackFor = RuntimeException.class)
public void insertUser() throws Exception {
// 插入用户
jdbcTemplate.update("INSERT INTO user(id, name) VALUES(1, 'terry')");
// 插入角色
jdbcTemplate.update("INSERT INTO role(user_id) VALUES(1)");
// 模拟后续逻辑报错
throw new Exception();
}
异常被捕捉了
方法内部捕捉异常没抛出,Spring是没法回滚的
@Transactional(rollbackFor = Exception.class)
public void insertUser3() {
try {
// 插入用户
jdbcTemplate.update("INSERT INTO user(id, name) VALUES(1, 'terry')");
// 插入角色
jdbcTemplate.update("INSERT INTO role(user_id) VALUES(1)");
// 模拟后续逻辑报错
throw new Exception();
} catch (Exception e) {
e.printStackTrace();
}
}
方法内部调用
a方法没异常,b方法异常,事务回滚成功。
@Transactional(rollbackFor = Exception.class)
public void insertUser4() {
jdbcTemplate.update("INSERT INTO user(id, name) VALUES(1, 'terry')");
insertRole();
}
public void insertRole() {
jdbcTemplate.update("INSERT INTO role(user_id) VALUES(1)");
throw new RuntimeException();
}
a方法异常,b方法没异常,事务回滚成功。
@Transactional(rollbackFor = Exception.class)
public void insertUser4() {
jdbcTemplate.update("INSERT INTO user(id, name) VALUES(1, 'terry')");
int i = 1 / 0;
insertRole();
}
public void insertRole() {
jdbcTemplate.update("INSERT INTO role(user_id) VALUES(1)");
}
a方法没有事务注解,b方法有事务注解,事务回滚失败
public void insertUser4() {
jdbcTemplate.update("INSERT INTO user(id, name) VALUES(1, 'terry')");
insertRole();
}
@Transactional(rollbackFor = Exception.class)
public void insertRole() {
jdbcTemplate.update("INSERT INTO role(user_id) VALUES(1)");
int i = 1 / 0;
}
两张表都会产生数据:
原因:SpringAOP代理机制,最后转换成内部类不能处理。
如何解决?针对这种问题SpringAOP有单独的方案,如下:
@Service
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
public class UserService {
/**
* 解决事务失效问题
* @throws Exception
*/
public void insertUser5() {
jdbcTemplate.update("INSERT INTO user(id, name) VALUES(1, 'terry')");
// 单独处理
UserService o = (UserService)AopContext.currentProxy();
o.insertRole();
}
@Transactional(rollbackFor = Exception.class)
public void insertRole() {
jdbcTemplate.update("INSERT INTO role(user_id) VALUES(1)");
int i = 1 / 0;
}
}
其它事务失效
使用多数据源非同一个事务管理器。