一、事务不生效(常见)
1.方法修饰符不是public
2.方法用final修饰
3.同一个类中调用事务方法,例如
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public void add(UserModel userModel) {
userMapper.insertUser(userModel);
// 调用事务方法,事务不生效
updateStatus(userModel);
}
// 事务方法
@Transactional
public void updateStatus(UserModel userModel) {
doSameThing();
}
}
4.类本身未注入spring,未被spring管理
5.多线程调用
6.存储引擎不支持事务
7.未开启事务,注意:
如果你使用的是springboot当然是不需要考虑事务未开启问题
但是如果你使用的还是传统的spring项目,就需要在applicationContext.xml文件中,手动配置事务相关参数 , 如果忘了配置,事务是不会生效的。
二、事务不回滚
1.错误的事务传播特性
我们在使用@Transactional注解时,是可以指定propagation参数的。
该参数的作用是指定事务的传播特性,spring目前支持7种传播特性:
REQUIRED 如果当前上下文中存在事务,那么加入该事务,如果不存在事务,创建一个事务。-----默认传播特性
SUPPORTS 如果当前上下文存在事务,则支持事务加入事务,如果不存在事务,则使用非事务的方式执行。
MANDATORY 如果当前上下文中存在事务,否则抛出异常。
REQUIRES_NEW 每次都会新建一个事务,并且同时将上下文中的事务挂起,执行当前新建事务完成以后,上下文事务恢复再执行。
NOT_SUPPORTED 如果当前上下文中存在事务,则挂起当前事务,然后新的方法在没有事务的环境中执行。
NEVER 如果当前上下文中存在事务,则抛出异常,否则在无事务环境上执行代码。
NESTED 如果当前上下文中存在事务,则嵌套事务执行,如果不存在事务,则新建事务。
@Service
public class UserService {
// 事务传播特性
@Transactional(propagation = Propagation.NEVER)
public void add(UserModel userModel) {
saveData(userModel);
updateData(userModel);
}
}
2.try...catch,异常被自己处理掉了,不会触发回滚
3.手动抛出了异常
4.自定义了回滚异常
在使用@Transactional注解声明事务时,有时我们想自定义回滚的异常,spring也是支持的。可以通过设置rollbackFor参数,来完成这个功能, 如果自定义的异常类型未能包含方法中的异常场景, 会导致不会回滚!
@Transactional(rollbackFor = BusinessException.class)
5.嵌套异常处理(不属于不回滚的情况,了解即可)
public class UserService {
@Autowired
private UserMapper userMapper;
@Autowired
private RoleService roleService;
// 此方法添加了事务管理机制
@Transactional
public void add(UserModel userModel) throws Exception {
userMapper.insertUser(userModel);
// 此处调用的方法本身也添加了事务管理
// 如果dootherThing方法异常,则doOtherThing回滚,add方法也会回滚
roleService.doOtherThing();
}
}
@Service
public class RoleService {
@Transactional(propagation = Propagation.NESTED)
public void doOtherThing() {
System.out.println("保存role表数据");
}
}
而以上代码中,有时只需要回滚部分代码,不需要回滚的部分使用try..catch抓取异常即可,例如
@Slf4j
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
@Autowired
private RoleService roleService;
@Transactional
public void add(UserModel userModel) throws Exception {
userMapper.insertUser(userModel);
try {
roleService.doOtherThing();
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
}