Spring之路(41)–注意规避@Transactional声明式事务失效的情况

简介: 本文目录1. 注意!2. 抛出检查型异常时事务失效3. 一个事务方法调用另一个事务方法时失效

1. 注意!

Spring中使用@Transactional的声明式事务是足够简单了,对底层逻辑进行了封装,开发人员拿来即用,方便快捷。


但是一定要注意在某些情况下,声明式事务会失效,事务是如此重要,一旦失效可能会带来灾难性后果,所以本篇我们来实验下。


2. 抛出检查型异常时事务失效

首先了解下一场类型:


Exception,受检查的异常,在程序中必须使用try…catch进行处理,遇到这种异常必须进行catch或throw,如果不处理,编译器会报错。例如IOException。

RuntimeException:非受检查的异常,可以不使用try…catch进行处理。例如常见的NullPointerException。

在我们的观念中,只要有异常,事务就应该回滚,实际上使用@Transactional时,默认只对非受检查异常回滚。例如:

  @Transactional
  public void addTwoBlog() throws Exception{
    BlogDo blog = new BlogDo();
    blog.setContent("测试");
    blogDao.insert(blog);
    blogDao.insert(blog);
    throw new RuntimeException();//非检查异常,回滚
  }

@Transactional

public void addTwoBlog() throws Exception{

 BlogDo blog = new BlogDo();

 blog.setContent("测试");

 blogDao.insert(blog);

 blogDao.insert(blog);

 int a=1/0;//非受检查异常,回滚

}


@Transactional

public void addTwoBlog() throws Exception{

 BlogDo blog = new BlogDo();

 blog.setContent("测试");

 blogDao.insert(blog);

 blogDao.insert(blog);

 throw new Exception();//注意!此处为受检查的异常,报错但不会回滚

}


OK,那么按正常情况下,我们认为一旦有异常,都应该回滚,此时只需要为注解添加rollbackFor=Exception.class属性即可。

例如:


   @Transactional(rollbackFor=Exception.class)//只要抛出异常就会回滚

public void addTwoBlog() throws Exception{

 BlogDo blog = new BlogDo();

 blog.setContent("测试");

 blogDao.insert(blog);

 blogDao.insert(blog);

 throw new Exception();

}


3. 一个事务方法调用另一个事务方法时失效

看如下案例:


@Transactional

public void startTransaction() throws Exception{

 this.addTwoBlog();

}


@Transactional(rollbackFor=Exception.class)

public void addTwoBlog() throws Exception{

 BlogDo blog = new BlogDo();

 blog.setContent("测试");

 blogDao.insert(blog);

 blogDao.insert(blog);

 throw new Exception();

}


startTransaction和addTwoBlog方法都是事务方法,且这两个方法事务特性不同(一个没有rollbackFor=Exception.class),如果我们调用startTransaction方法,则addTwoBlog中的事务并不会生效。


也就是说,如果在同一个bean中,一个事务方法调用另一个事务方法,可能会导致被调用的事务方法的事务失效!


这是因为Spring的声明式事务使用了代理,具体机制此处不再探讨,但是一定要规避这种事务失效的场景。我们可以通过将对数据库的操作放到一个bean方法里来解决这个问题。

相关文章
|
2天前
|
Java 开发者 Spring
深入解析 @Transactional:Spring 事务管理的艺术及实战应对策略
深入解析 @Transactional:Spring 事务管理的艺术及实战应对策略
7 2
|
12天前
|
XML Java 数据库
Spring框架第五章(声明式事务)
Spring框架第五章(声明式事务)
|
18天前
|
负载均衡 前端开发 Java
OpenFeign:Spring Cloud声明式服务调用组件
该文本是关于OpenFeign在Spring Cloud中的使用的问答总结。涉及的问题包括:OpenFeign是什么,Feign与OpenFeign的区别,如何使用OpenFeign进行远程服务调用,OpenFeign的超时控制以及日志增强。OpenFeign被描述为Spring官方的声明式服务调用和负载均衡组件,它支持使用注解进行接口定义和服务调用,如@FeignClient和@EnableFeignClients。OpenFeign与Feign的主要区别在于OpenFeign支持Spring MVC注解。超时控制通过Ribbon进行设置,默认超时时间为1秒。
|
19天前
|
Java 开发者 Spring
spring事务类型,事务传递,隔离级别?
spring事务类型,事务传递,隔离级别?
|
2天前
|
Java Spring
Spring Boot中的事务管理策略
Spring Boot中的事务管理策略
|
2天前
|
Java 数据库连接 开发者
在Spring的try-catch块中手动实现事务回滚
在Spring的try-catch块中手动实现事务回滚
6 0
|
2天前
|
XML Java 数据库
Spring5系列学习文章分享---第五篇(事务概念+特性+案例+注解声明式事务管理+参数详解 )
Spring5系列学习文章分享---第五篇(事务概念+特性+案例+注解声明式事务管理+参数详解 )
6 0
|
2天前
|
Java Spring
Spring Boot中的事务管理策略
Spring Boot中的事务管理策略
|
4天前
|
缓存 算法 Java
spring-三级缓存-生命周期-spring事务-IOC-AOP
spring-三级缓存-生命周期-spring事务-IOC-AOP
|
4天前
|
缓存 Java 数据库连接
spring中注解驱动事务框架的源码
spring中注解驱动事务框架的源码