前言
日常开发中,我们经常使用到spring
事务。最近星球一位还有去美团面试,被问了这么一道面试题: Spring 事务在哪几种情况下会不生效? 今天跟大家聊聊,spring
事务不生效的15
种场景。
1. 你的service类没有被Spring管理
//@Service (注释了@Service)
public class TianLuoServiceImpl implements TianLuoService {
@Autowired
private TianLuoMapper tianLuoMapper;
@Autowired
private TianLuoFlowMapper tianLuoFlowMapper;
@Transactional
public void addTianLuo(TianLuo tianluo) {
//保存tianluo实体数据库记录
tianLuoMapper.save(tianluo);
//保存tianluo流水数据库记录
tianLuoFlowMapper.saveFlow(buildFlowByTianLuo(tianluo));
}
}
复制代码
- 事务不生效的原因:上面例子中,
@Service
注解注释之后,spring
事务(@Transactional
)没有生效,因为Spring
事务是由AOP
机制实现的,也就是说从Spring IOC
容器获取bean
时,Spring
会为目标类创建代理,来支持事务的。但是@Service
被注释后,你的service
类都不是spring
管理的,那怎么创建代理类来支持事务呢。 - 解决方案:加上
@Service
注解。
2.没有在Spring配置文件中启用事务管理器
@Configuration
public class AppConfig {
// 没有配置事务管理器
}
@Service
public class MyService {
@Transactional
public void doSomething() {
// ...
}
}
复制代码
- 事务不生效的原因:没有在
AppConfig
中配置事务管理器,因此Spring
无法创建事务代理对象,导致事务不生效。即使在MyService
中添加了@Transactional
注解,该方法也不会被Spring
管理的事务代理拦截。 - 解决方案:为了解决这个问题,应该在
AppConfig
中配置一个事务管器。例如:
@Configuration
public class AppConfig {
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
}
@Service
public class MyService {
@Transactional
public void doSomething() {
// ...
}
}
复制代码
如果是
Spring Boot
项目,它默认会自动配置事务管理器并开启事务支持。
3. 事务方法被final、static关键字修饰
@Service
public class TianLuoServiceImpl {
@Autowired
private TianLuoMapper tianLuoMapper;
@Autowired
private TianLuoFlowMapper tianLuoFlowMapper;
@Transactional
public final void addTianLuo(TianLuo tianluo) {
//保存tianluo实体数据库记录
tianLuoMapper.save(tianluo);
//保存tianluo流水数据库记录
tianLuoFlowMapper.saveFlow(buildFlowByTianLuo(tianluo));
}
}
复制代码
- 事务不生效的原因:如果一个方法被声明为
final
或者static
,则该方法不能被子类重写,也就是说无法在该方法上进行动态代理,这会导致Spring
无法生成事务代理对象来管理事务。 - 解决方案:
addTianLuo
事务方法不要用final
修饰或者static
修饰。
4. 同一个类中,方法内部调用
@Service
public class TianLuoServiceImpl implements TianLuoService {
@Autowired
private TianLuoMapper tianLuoMapper;
@Autowired
private TianLuoFlowMapper tianLuoFlowMapper;
public void addTianLuo(TianLuo tianluo){
// 调用内部的事务方法
this.executeAddTianLuo(tianluo);