多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
## @Transactional 失效场景 1. 业务代码被try catch 包裹:由于异常被捕获后没有抛出,导致无法触发aop的异常通知里的回滚。**如果某段代码不想抛出异常,可以这样处理** ``` @Transactional(rollbackFor = Exception.class) public String add() { try { userService.add(); roleService.add(); } catch (Exception e) { log.error("") } } ``` 2. 业务中间使用统一消息处理返回错误信息:这样表示代码正常执行完成,只是返回给前端的消息是错误信息,不会触发aop的异常通知里的回滚 ``` @Transactional(rollbackFor = Exception.class) public String add() { map.insert(user) if(true) { // 这样返回,上面的insert不回滚 return R.error(''); // 使用自定义异常抛出错误信息 // throw new BusinessException(""); } } ``` 3. 方法不在同一个大的事务下:之前遇到同事把业务代码写在controller层,导致调用的方法都正确添加了事务,但是事务之间相互独立 ``` // service1和service2 的add 都各自添加了事务注解 当执行到 service2.add() 方法时,service1的add方法自己的事务流程已经结束,数据也已经保存到数据库了,后边方法报错不会影响它 @GetMapping("/add") public R<String> add() { service1.add(); service2.add(); return R.ok(); } 应该放到一个大的事务下 @GetMapping("/add") public R<String> add() { service.add(); return R.ok(); } @Transactional(rollbackFor = Exception.class) public void add() { service1.add(); service2.add(); } ``` 4. 注解属性 rollbackFor 设置错误 @Transactional 非受检异常会回滚,像IOException 就不会回滚 ``` @Override @Transactional // 应该使用这个 //@Transactional(rollbackFor = Exception.class) public void save() throws IOException { add(); throw new IOException(); } ``` 5. 同一个类中方法调用 具体查看[spring事务本类调用](https://www.kancloud.cn/wsj-/java/3094215) 文章 6. @Transactional 注解属性 propagation 设置错误 1. TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。 2. TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。 3. TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。比如 IO操作的错误都不会回滚 7. 数据库引擎不支持事务:现在基本不会有这个问题,都是用 Innodb 存储引擎了 (5.5版本之前)低版本的 MySQL以前都是用的MySQL自己的存储引擎 MyISAM, 这个不支持事务, 现在的MySQL默认都是使用的第三方存储引擎InnoDB, 这个是支持事务的 8. @Transactional 应用在非 public 修饰的方法上,规定只能是public的