事物失效的8种情况及解决办法

事物失效的8种情况及解决办法

数据库引擎不支持事务

这里以 MySQL 为例,其 MyISAM 引擎是不支持事务操作的,InnoDB 才是支持事务的引擎,一般要支持事务都会使用 InnoDB,这时候选择支持事物的数据库即可(好像是废话,哈哈哈)

没有被 Spring 管理

这个好像没什么可说的,脱离了Spring的管理,还谈什么Spring事物管理。

方法不是 public 的

@Transactional 只能用于 public 的方法上,否则事务不会失效,如果要用在非 public 方法上,可以开启 AspectJ 代理模式。

数据源没有配置事务管理器

相当于没开启事务管理,如果不是Springboot情况需要进行如下操作。

@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
    return new DataSourceTransactionManager(dataSource);
}

如果是SpringBoot,在启动类上直接加上注解@EnableTransactionManagement即可。

传播特性配错了

传播特性配置成,Propagation.NOT_SUPPORTED或者Propagation.NOT_SUPPORTED,改成支持事物的传播特性即可。

异常类型错误

因为默认的异常类型是运行时异常,如果抛出了其他异常就不生效。
解决方式:
1、将异常改成运行时异常
2、指定异常进行事物回滚,如:@Transactional(rollbackFor = Exception.class)

异常被吃掉了

如果你代码这么写,事物不生效:

    @Transactional(rollbackFor = Exception.class)
    public void updateUser2() {
     try {        
     int r1 = userInfoDAO.updateUserName(1,"3");
        int r2 = userInfoDAO.updateUserName(2,"4");
        if (r2==1){
            throw new RuntimeException();
        }
        
        }catch (Exception e){

        }
    }

 

解决办法: 必须要抛出异常,否则Spring事务管理,不会走到回滚逻辑

类内部调用

 

@Service
public class UserInfoService {
    public void justUpdate(){
        updateUser2();
    }
    @Transactional(rollbackFor = Exception.class)
    public void updateUser2() {

    }
}

 

上述代码不生效,因为内部调用不会涉及到代理类的调用,更不会有AOP的增强,因此不会生效。
解决办法:
1、自注入

@Service
public class UserInfoService {
   @Autowired
    private UserInfoService userInfoService;
    public void justUpdate(){
        userInfoService.updateUser2();
    }
    @Transactional(rollbackFor = Exception.class)
    public void updateUser2() {

    }
}

 

2、Spring上下文

@Service
public class UserInfoService {
    ApplicationContext applicationContext;
    public void justUpdate(){
           UserInfoService userInfoService = (UserInfoService) applicationContext.getBean("userInfoService");
        userInfoService.updateUser2();
    }
    @Transactional(rollbackFor = Exception.class)
    public void updateUser2() {
    }
}

 

3、获取他的代理类,直接调用代理类

 

@Service
public class UserInfoService {
    public void justUpdate(){
           ((UserInfoService) AopContext.currentProxy()).updateUser2();
    }
    @Transactional(rollbackFor = Exception.class)
    public void updateUser2() {
    }
}

 

因为相信,所以看见.
原文地址:https://www.cnblogs.com/zeenzhou/p/15219794.html