Spring的事务失效的几种情况

467 阅读2分钟

一.源头,源头都不支持事务了,@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官方文档有说明