一.源头,源头都不支持事务了,@Transaction注解肯定也没啥用
1.数据库不支持事务,InnoDB支持事务,Myisam不支持
二.是否让spring框架来帮你管理事务,你都没把管理事务的权力交给spring,加了它的注解也没啥用 1.数据源没有配置平台事务管理器
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
2.使用的@Transaction注解类没有被spring实例化管理
//@Service 这里没有加这个注解,也就是没有把这个类创建的对象交给spring来管理
public class TransactionService {
@Transactional
public void transaction(){
}
}
3.设置的propagation属性不需要事务,你都告诉人家不要事务了,自然就没有事务
@Transactional(propagation = Propagation.NOT_SUPPORTED )
public void transaction(){
}
三.因为自己方法调用方式导致的失效 1.同一个类中,在一个没有事务的方法中直接调用另一个有事务的方法,这时候那个加了事务注解方法没有效果,个人理解为,这里是直接类内方法调用,不是用spring管理的bean对象调用,所以spring检测不到@Transaction,那么也就没有效果了
//没事务的方法
public void noTransaction(){
transaction();
}
//有事务的方法
@Transactional
public void transaction(){
}
如果有场景是非要拆开成两个方法,一个有事务,一个没有事务,例如场景是没有事务的方法是要那有事务的方法(主要业务)插入数据库的某些东西,但是这个方法又不想影响主业务,如果两个方法都在同一个事务的话,那此时非主业务拿不到主业务提交事务后才有的字段。 解决方式: 1.在这个类中定义一个这个类自己的bean对象,有点绕,其实就像这样
@Service
public class TransactionService {
@Resource
private TransactionService transactionService;
//没事务的方法
public void noTransaction(){
transactionService.transaction();
}
//有事务的方法
@Transactional
public void transaction(){
}
}
2.把这个方法放到另一个类中,然后就跟调用其它类的方法一样调用
四.由于对异常的处理导致的,因为@Transaction默认情况下是通过拦截方法返回的RuntimeException来回滚的,那么有如下几种情况
1.在service对异常进行了try{}catch{}处理,那么也就不会抛出异常,不抛出异常的话,@Transaction也就失效了
//有事务的方法
@Transactional
public void transaction(){
try{
}catch (Exception e){
我把异常都捕获了
}
}
2.抛出了异常,但是异常不是RuntimeException类型的,那么事务也没有用了
//有事务的方法
@Transactional
public void transaction(){
throw new Exception("我不是runtimeException");
}
五.方法本身的问题 方法不是public的也不行,spring官方文档有说明