本文讲解 Spring Boot 如何使用声明式事务管理。

声明式事务

Spring 支持声明式事务,使用 @Transactional 注解在方法上表明这个方法需要事务支持。此时,Spring 拦截器会在这个方法调用时,开启一个新的事务,当方法运行结束且无异常的情况下,提交这个事务。

Spring 提供一个 @EnableTransactionManagement 注解在配置类上来开启声明式事务的支持。使用了 @EnableTransactionManagement 后,Spring 会自动扫描注解 @Transactional 的方法和类。

Spring Boot默认集成事务

Spring Boot 默认集成事务,所以无须手动开启使用 @EnableTransactionManagement 注解,就可以用 @Transactional注解进行事务管理。我们如果使用到 spring-boot-starter-jdbc 或 spring-boot-starter-data-jpa,Spring Boot 会自动默认分别注入
DataSourceTransactionManager 或 JpaTransactionManager。

实战演练

我们在前文「Spring Boot 揭秘与实战(二) 数据存储篇 - MySQL」的案例上,进行实战演练。

实体对象

我们先创建一个实体对象。为了便于测试,我们对外提供一个构造方法。

  1. public class Author {
  2. private Long id;
  3. private String realName;
  4. private String nickName;
  5.  
  6. public Author() {}
  7. public Author(String realName, String nickName) {
  8. this.realName = realName;
  9. this.nickName = nickName;
  10. }
  11. // SET和GET方法
  12. }

DAO 相关

这里,为了测试事务,我们只提供一个方法新增方法。

  1. @Repository("transactional.authorDao")
  2. public class AuthorDao {
  3.  
  4. @Autowired
  5. private JdbcTemplate jdbcTemplate;
  6.  
  7. public int add(Author author) {
  8. return jdbcTemplate.update("insert into t_author(real_name, nick_name) values(?, ?)",
  9. author.getRealName(), author.getNickName());
  10. }
  11.  
  12. }

Service 相关

我们提供三个方法。通过定义 Author 的 realName 字段长度必须小于等于 5,如果字段长度超过规定长度就会触发参数异常。

值得注意的是,noRollbackFor 修饰表明不做事务回滚,rollbackFor 修饰的表明需要事务回滚。

  1. @Service("transactional.authorService")
  2. public class AuthorService {
  3.  
  4. @Autowired
  5. private AuthorDao authorDao;
  6.  
  7. public int add1(Author author) {
  8. int n = this.authorDao.add(author);
  9. if(author.getRealName().length() > 5){
  10. throw new IllegalArgumentException("author real name is too long.");
  11. }
  12. return n;
  13. }
  14.  
  15. @Transactional(noRollbackFor={IllegalArgumentException.class})
  16. public int add2(Author author) {
  17. int n = this.authorDao.add(author);
  18. if(author.getRealName().length() > 5){
  19. throw new IllegalArgumentException("author real name is too long.");
  20. }
  21. return n;
  22. }
  23.  
  24. @Transactional(rollbackFor={IllegalArgumentException.class})
  25. public int add3(Author author) {
  26. int n = this.authorDao.add(author);
  27. if(author.getRealName().length() > 5){
  28. throw new IllegalArgumentException("author real name is too long.");
  29. }
  30. return n;
  31. }
  32. }

测试,测试

  1. @RunWith(SpringJUnit4ClassRunner.class)
  2. @SpringApplicationConfiguration(WebMain.class)
  3. public class TransactionalTest {
  4.  
  5. @Autowired
  6. protected AuthorService authorService;
  7.  
  8. //@Test
  9. public void add1() throws Exception {
  10. authorService.add1(new Author("梁桂钊", "梁桂钊"));
  11. authorService.add1(new Author("LiangGzone", "LiangGzone"));
  12. }
  13.  
  14. //@Test
  15. public void add2() throws Exception {
  16. authorService.add2(new Author("梁桂钊", "梁桂钊"));
  17. authorService.add2(new Author("LiangGzone", "LiangGzone"));
  18. }
  19.  
  20. @Test
  21. public void add3() throws Exception {
  22. authorService.add3(new Author("梁桂钊", "梁桂钊"));
  23. authorService.add3(new Author("LiangGzone", "LiangGzone"));
  24. }
  25. }

我们分别对上面的三个方法进行测试,只有最后一个方法进行了事务回滚。

源代码

相关示例完整代码: springboot-action

(完)

 

Spring Boot 揭秘与实战(二) 数据存储篇 - 声明式事务管理

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2021-12-27
  • 2021-08-04
  • 2022-01-10
  • 2021-07-13
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案