spring-transaction源码分析(1)概述和事务传播级别

打印 上一主题 下一主题

主题 928|帖子 928|积分 2784

spring-tx概述

spring-tx包使用注解驱动和AOP通知将事务开启、提交/回滚、以及复杂的传播机制封装了起来,开发者不再需要编写事务管理的代码,而是可以只关注自己的业务逻辑。
本文将简单介绍spring-tx使用步骤以及七种事务传播级别。
后续文章会阅读源码,深入分析spring-tx aop通知、七种事务传播级别以及事务开启/提交/回滚的实现方式。
使用步骤


  • 导入spring-tx依赖
  • 使用@EnableTransactionManagement注解为应用开启事务支持
  • 向spring容器注入一个TransactionManager实现,一般使用DataSourceTransactionManager类
  • 在需要事务的业务方法上标注@Transactional注解即可为方法开启事务通知
Transactional注解参数


  • transactionManager - 手动指定要使用的事务管理器
  • propagation - 事务传播级别
  • isolation - 事务隔离级别
  • timeout - 事务超时时长
  • rollbackFor - 发生指定的异常时回滚事务
事务传播级别

七种级别


  • REQUIRED - Support a current transaction, create a new one if none exists. 支持当前存在的事务,如果当前没有事务,则新创建一个。默认的传播级别。
  • SUPPORTS - Support a current transaction, execute non-transactionally if none exists. 支持当前存在的事务,如果当前没有事务,则在无事务状态下运行。
    1. For transaction managers with transaction synchronization, SUPPORTS is slightly different from
    2. no transaction at all, as it defines a transaction scope that synchronization will apply for.
    3. As a consequence, the same resources (JDBC Connection, Hibernate Session, etc) will be shared
    4. for the entire specified scope. Note that this depends on the actual synchronization configuration
    5. of the transaction manager.
    复制代码
  • MANDATORY - Support a current transaction, throw an exception if none exists. 支持当前存在的事务,如果当前没有事务,则抛出异常。
  • REQUIRES_NEW - Create a new transaction, and suspend the current transaction if one exists. 创建新事务,如果当前已存在事务则挂起这个事务,再创建新事务。
  • NOT_SUPPORTED - Execute non-transactionally, suspend the current transaction if one exists. 在无事务状态下运行,如果当前已存在事务则挂起这个事务。
  • NEVER - Execute non-transactionally, throw an exception if a transaction exists. 在无事务状态下运行,如果当前已存在事务,则抛出异常。
  • NESTED - Execute within a nested transaction if a current transaction exists, behave like REQUIRED otherwise. 如果当前已存在事务,则嵌入到当前事务中运行,否则和REQUIRED效果一样。
示例方法

在测试事务传播级别的示例中,会反复使用以下6个方法,只是给Transactional添加的参数不同而已,此处记录一下这几个方法:
  1. public void insertBlogList(List<Blog> blogList) {
  2.   for (int i = 0; i < blogList.size(); i++) {
  3.     this.blogMapper.insertBlog(blogList.get(i));
  4.   }
  5. }
  6. public void deleteBlogByCondition(BlogSearchParameter parameter) {
  7.   List<Blog> blogs = this.blogMapper.selectBlogByParameter(parameter);
  8.   for (Blog blog : blogs) {
  9.     this.blogMapper.deleteBlog(blog.getId());
  10.   }
  11.   // 抛出一个RuntimeException
  12.   throw new RuntimeException("deleteBlogByCondition抛出一个异常");
  13. }
  14. public void insertAndDeleteBlogList1(List<Blog> blogList, BlogSearchParameter parameter) {
  15.   // 这里从spring容器获取service对象,避免事务失效
  16.   BlogRequiredTxService blogService =
  17.       this.applicationContext.getBean(BlogRequiredTxService.class);
  18.   // 插入数据
  19.   blogService.insertBlogList(blogList);
  20.   // 删除数据
  21.   blogService.deleteBlogByCondition(parameter);
  22. }
  23. public void insertAndDeleteBlogList2(List<Blog> blogList, BlogSearchParameter parameter) {
  24.   BlogRequiredTxService blogService =
  25.       this.applicationContext.getBean(BlogRequiredTxService.class);
  26.   // 插入数据
  27.   blogService.insertBlogList(blogList);
  28.   // 删除数据
  29.   try {
  30.     blogService.deleteBlogByCondition(parameter);
  31.   } catch (Exception e) {
  32.     System.err.printf("Err:%s%n", e.getMessage());
  33.   }
  34.   System.out.println("继续插入数据");
  35.   // 继续插入数据
  36.   blogService.insertBlogList(blogList);
  37. }
  38. public void insertAndDeleteBlogList3(List<Blog> blogList, BlogSearchParameter parameter) {
  39.   BlogRequiredTxService blogService =
  40.       this.applicationContext.getBean(BlogRequiredTxService.class);
  41.   // 插入数据
  42.   blogService.insertBlogList(blogList);
  43.   // 删除数据
  44.   blogService.deleteBlogByCondition(parameter);
  45. }
  46. public void insertAndDeleteBlogList4(List<Blog> blogList, BlogSearchParameter parameter) {
  47.   BlogRequiredTxService blogService =
  48.       this.applicationContext.getBean(BlogRequiredTxService.class);
  49.   // 插入数据
  50.   blogService.insertBlogList(blogList);
  51.   // 删除数据
  52.   try {
  53.     blogService.deleteBlogByCondition(parameter);
  54.   } catch (Exception e) {
  55.     System.err.printf("Err:%s%n", e.getMessage());
  56.   }
  57.   System.out.println("继续插入数据");
  58.   // 继续插入数据
  59.   blogService.insertBlogList(blogList);
  60. }
复制代码
传播级别详细说明

REQUIRED

Support a current transaction, create a new one if none exists.
支持当前存在的事务,如果当前没有事务,则新创建一个。默认的传播级别。
  1. @Transactional(propagation = Propagation.REQUIRED)
  2. public void insertBlogList(List<Blog> blogList) {
  3.   for (int i = 0; i < blogList.size(); i++) {
  4.     this.blogMapper.insertBlog(blogList.get(i));
  5.   }
  6. }
  7. @Transactional(propagation = Propagation.REQUIRED)
  8. public void deleteBlogByCondition(BlogSearchParameter parameter) {
  9.   List<Blog> blogs = this.blogMapper.selectBlogByParameter(parameter);
  10.   for (Blog blog : blogs) {
  11.     this.blogMapper.deleteBlog(blog.getId());
  12.   }
  13.   // 抛出一个RuntimeException
  14.   throw new RuntimeException("deleteBlogByCondition抛出一个异常");
  15.   // 如果调用方法前,没有事务,则delete操作都会回滚
  16.   // 如果调用方法前,已经存在事务,则之前的事务操作都会回滚
  17. }
  18. @Transactional(propagation = Propagation.REQUIRED)
  19. public void insertAndDeleteBlogList1(List<Blog> blogList, BlogSearchParameter parameter) {
  20.   BlogRequiredTxService blogService =
  21.       this.applicationContext.getBean(BlogRequiredTxService.class);
  22.   // 插入数据
  23.   blogService.insertBlogList(blogList);
  24.   // 删除数据
  25.   blogService.deleteBlogByCondition(parameter);
  26.   // deleteBlogByCondition方法抛出异常之后,则insertAndDeleteBlogList1方法的操作会回滚
  27.   // 如果insertAndDeleteBlogList1方法在另一个事务中,则之前的事务操作都会回滚
  28. }
  29. @Transactional(propagation = Propagation.REQUIRED)
  30. public void insertAndDeleteBlogList2(List<Blog> blogList, BlogSearchParameter parameter) {
  31.   BlogRequiredTxService blogService =
  32.       this.applicationContext.getBean(BlogRequiredTxService.class);
  33.   // 插入数据
  34.   blogService.insertBlogList(blogList);
  35.   // 删除数据
  36.   try {
  37.     blogService.deleteBlogByCondition(parameter);
  38.   } catch (Exception e) {
  39.     System.err.printf("Err:%s%n", e.getMessage());
  40.   }
  41.   System.out.println("继续插入数据");
  42.   // 继续插入数据
  43.   blogService.insertBlogList(blogList);
  44.   // deleteBlogByCondition方法抛出异常之后,会执行catch代码块,之后继续向下执行,
  45.   // 执行blogService.insertBlogList(blogList)方法之后,
  46.   // 在commit的时候检测到insertAndDeleteBlogList2方法rollback-only状态,会抛出异常:
  47.   // org.springframework.transaction.UnexpectedRollbackException:
  48.   // Transaction rolled back because it has been marked as rollback-only
  49. }
  50. public void insertAndDeleteBlogList3(List<Blog> blogList, BlogSearchParameter parameter) {
  51.   BlogRequiredTxService blogService =
  52.       this.applicationContext.getBean(BlogRequiredTxService.class);
  53.   // 插入数据
  54.   blogService.insertBlogList(blogList);
  55.   // 删除数据
  56.   blogService.deleteBlogByCondition(parameter);
  57.   // 由于insertAndDeleteBlogList3方法没有标注Transactional注解:
  58.   // blogService.insertBlogList(blogList)方法插入的数据会提交保存下来
  59.   // blogService.deleteBlogByCondition(parameter)方法的删除操作会回滚
  60. }
  61. public void insertAndDeleteBlogList4(List<Blog> blogList, BlogSearchParameter parameter) {
  62.   BlogRequiredTxService blogService =
  63.       this.applicationContext.getBean(BlogRequiredTxService.class);
  64.   // 插入数据
  65.   blogService.insertBlogList(blogList);
  66.   // 删除数据
  67.   try {
  68.     blogService.deleteBlogByCondition(parameter);
  69.   } catch (Exception e) {
  70.     System.err.printf("Err:%s%n", e.getMessage());
  71.   }
  72.   System.out.println("继续插入数据");
  73.   // 继续插入数据
  74.   blogService.insertBlogList(blogList);
  75.   // 由于insertAndDeleteBlogList3方法没有标注Transactional注解:
  76.   // blogService.insertBlogList(blogList)方法插入的数据会提交保存下来
  77.   // blogService.deleteBlogByCondition(parameter)方法的删除操作会回滚
  78.   // 之后会继续执行blogService.insertBlogList(blogList)再插入数据
  79. }
复制代码
REQUIRES_NEW

Create a new transaction, and suspend the current transaction if one exists.
创建新事务,如果当前已存在事务则挂起这个事务,再打开一个新的数据库连接创建新事务。
  1. @Transactional(propagation = Propagation.REQUIRES_NEW)
  2. public void insertBlogList(List<Blog> blogList) {
  3.   for (Blog blog : blogList) {
  4.     this.blogMapper.insertBlog(blog);
  5.   }
  6.   try {
  7.     TimeUnit.SECONDS.sleep(15);
  8.   } catch (InterruptedException e) {
  9.     e.printStackTrace();
  10.   }
  11. }
  12. @Transactional(propagation = Propagation.REQUIRES_NEW)
  13. public void deleteBlogByCondition(BlogSearchParameter parameter) {
  14.   List<Blog> blogs = this.blogMapper.selectBlogByParameter(parameter);
  15.   for (Blog blog : blogs) {
  16.     this.blogMapper.deleteBlog(blog.getId());
  17.   }
  18.   // 抛出一个RuntimeException
  19.   throw new RuntimeException("deleteBlogByCondition抛出一个异常");
  20.   // 只会回滚delete操作,因为该方法是新创建的事务
  21. }
  22. @Transactional
  23. public void insertAndDeleteBlogList1(List<Blog> blogList, BlogSearchParameter parameter) {
  24.   BlogRequiresNewTxService blogService =
  25.       this.applicationContext.getBean(BlogRequiresNewTxService.class);
  26.   // 插入数据
  27.   blogService.insertBlogList(blogList);
  28.   // 删除数据
  29.   blogService.deleteBlogByCondition(parameter);
  30.   // blogService.insertBlogList(blogList)成功
  31.   // blogService.deleteBlogByCondition(parameter)会回滚
  32.   // 同时insertAndDeleteBlogList1中的事务也会回滚
  33.   // 如果使用show processlist查看客户端进程,
  34.   // 可以看到insertBlogList和deleteBlogByCondition方法创建了新的数据库连接
  35. }
  36. @Transactional
  37. public void insertAndDeleteBlogList2(List<Blog> blogList, BlogSearchParameter parameter) {
  38.   BlogRequiresNewTxService blogService =
  39.       this.applicationContext.getBean(BlogRequiresNewTxService.class);
  40.   // 插入数据
  41.   blogService.insertBlogList(blogList);
  42.   // 删除数据
  43.   try {
  44.     blogService.deleteBlogByCondition(parameter);
  45.   } catch (Exception e) {
  46.     System.err.printf("Err:%s%n", e.getMessage());
  47.   }
  48.   System.out.println("继续插入数据");
  49.   // 继续插入数据
  50.   blogService.insertBlogList(blogList);
  51.   // blogService.insertBlogList(blogList)成功
  52.   // blogService.deleteBlogByCondition(parameter)会回滚
  53.   // 此时insertAndDeleteBlogList1中的事务不会回滚,因为deleteBlogByCondition(parameter)的异常被"吞掉了"
  54.   // 后续的blogService.insertBlogList(blogList)也会成功
  55. }
  56. public void insertAndDeleteBlogList3(List<Blog> blogList, BlogSearchParameter parameter) {
  57.   BlogRequiresNewTxService blogService =
  58.       this.applicationContext.getBean(BlogRequiresNewTxService.class);
  59.   // 插入数据
  60.   blogService.insertBlogList(blogList);
  61.   // 删除数据
  62.   blogService.deleteBlogByCondition(parameter);
  63.   // blogService.insertBlogList(blogList)成功
  64.   // blogService.deleteBlogByCondition(parameter)会回滚
  65. }
  66. public void insertAndDeleteBlogList4(List<Blog> blogList, BlogSearchParameter parameter) {
  67.   BlogRequiresNewTxService blogService =
  68.       this.applicationContext.getBean(BlogRequiresNewTxService.class);
  69.   // 插入数据
  70.   blogService.insertBlogList(blogList);
  71.   // 删除数据
  72.   try {
  73.     blogService.deleteBlogByCondition(parameter);
  74.   } catch (Exception e) {
  75.     System.err.printf("Err:%s%n", e.getMessage());
  76.   }
  77.   System.out.println("继续插入数据");
  78.   // 继续插入数据
  79.   blogService.insertBlogList(blogList);
  80.   // blogService.insertBlogList(blogList)成功
  81.   // blogService.deleteBlogByCondition(parameter)会回滚
  82.   // 后续的blogService.insertBlogList(blogList)也会成功
  83. }
复制代码
MANDATORY

Support a current transaction, throw an exception if none exists.
支持当前存在的事务,如果当前没有事务,则抛出异常。
  1. @Transactional(propagation = Propagation.MANDATORY)
  2. public void insertBlogList(List<Blog> blogList) {
  3.   for (Blog blog : blogList) {
  4.     this.blogMapper.insertBlog(blog);
  5.   }
  6.   // 单独调用此方法时抛错:
  7.   // org.springframework.transaction.IllegalTransactionStateException:
  8.   // No existing transaction found for transaction marked with propagation 'mandatory'
  9. }
  10. @Transactional(propagation = Propagation.MANDATORY)
  11. public void deleteBlogByCondition(BlogSearchParameter parameter) {
  12.   List<Blog> blogs = this.blogMapper.selectBlogByParameter(parameter);
  13.   for (Blog blog : blogs) {
  14.     this.blogMapper.deleteBlog(blog.getId());
  15.   }
  16.   // 抛出一个RuntimeException
  17.   throw new RuntimeException("deleteBlogByCondition抛出一个异常");
  18.   // 单独调用此方法时抛错:
  19.   // org.springframework.transaction.IllegalTransactionStateException:
  20.   // No existing transaction found for transaction marked with propagation 'mandatory'
  21. }
  22. @Transactional
  23. public void insertAndDeleteBlogList1(List<Blog> blogList, BlogSearchParameter parameter) {
  24.   BlogMandatoryTxService blogService =
  25.       this.applicationContext.getBean(BlogMandatoryTxService.class);
  26.   // 插入数据
  27.   blogService.insertBlogList(blogList);
  28.   // 删除数据
  29.   blogService.deleteBlogByCondition(parameter);
  30.   // deleteBlogByCondition方法抛出异常之后,则insertAndDeleteBlogList1方法的操作会回滚
  31.   // 如果insertAndDeleteBlogList1方法在另一个事务中,则之前的事务操作都会回滚
  32. }
  33. @Transactional
  34. public void insertAndDeleteBlogList2(List<Blog> blogList, BlogSearchParameter parameter) {
  35.   BlogMandatoryTxService blogService =
  36.       this.applicationContext.getBean(BlogMandatoryTxService.class);
  37.   // 插入数据
  38.   blogService.insertBlogList(blogList);
  39.   // 删除数据
  40.   try {
  41.     blogService.deleteBlogByCondition(parameter);
  42.   } catch (Exception e) {
  43.     System.err.printf("Err:%s%n", e.getMessage());
  44.   }
  45.   System.out.println("继续插入数据");
  46.   // 继续插入数据
  47.   blogService.insertBlogList(blogList);
  48.   // deleteBlogByCondition方法抛出异常之后,会执行catch代码块,之后继续向下执行,
  49.   // 执行blogService.insertBlogList(blogList)方法之后,
  50.   // 在commit的时候检测到insertAndDeleteBlogList2方法rollback-only状态,会抛出异常:
  51.   // org.springframework.transaction.UnexpectedRollbackException:
  52.   // Transaction rolled back because it has been marked as rollback-only
  53. }
  54. public void insertAndDeleteBlogList3(List<Blog> blogList, BlogSearchParameter parameter) {
  55.   BlogMandatoryTxService blogService =
  56.       this.applicationContext.getBean(BlogMandatoryTxService.class);
  57.   // 插入数据
  58.   blogService.insertBlogList(blogList);
  59.   // 删除数据
  60.   blogService.deleteBlogByCondition(parameter);
  61.   // 抛错:
  62.   // org.springframework.transaction.IllegalTransactionStateException:
  63.   // No existing transaction found for transaction marked with propagation 'mandatory'
  64. }
  65. public void insertAndDeleteBlogList4(List<Blog> blogList, BlogSearchParameter parameter) {
  66.   BlogMandatoryTxService blogService =
  67.       this.applicationContext.getBean(BlogMandatoryTxService.class);
  68.   // 插入数据
  69.   blogService.insertBlogList(blogList);
  70.   // 删除数据
  71.   try {
  72.     blogService.deleteBlogByCondition(parameter);
  73.   } catch (Exception e) {
  74.     System.err.printf("Err:%s%n", e.getMessage());
  75.   }
  76.   System.out.println("继续插入数据");
  77.   // 继续插入数据
  78.   blogService.insertBlogList(blogList);
  79.   // 抛错:
  80.   // org.springframework.transaction.IllegalTransactionStateException:
  81.   // No existing transaction found for transaction marked with propagation 'mandatory'
  82. }
复制代码
SUPPORTS

Support a current transaction, execute non-transactionally if none exists.
支持当前存在的事务,如果当前没有事务,则在无事务状态下运行。
  1. @Transactional(propagation = Propagation.SUPPORTS)
  2. public void insertBlogList(List<Blog> blogList) {
  3.   for (Blog blog : blogList) {
  4.     this.blogMapper.insertBlog(blog);
  5.   }
  6. }
  7. @Transactional(propagation = Propagation.SUPPORTS)
  8. public void deleteBlogByCondition(BlogSearchParameter parameter) {
  9.   List<Blog> blogs = this.blogMapper.selectBlogByParameter(parameter);
  10.   for (Blog blog : blogs) {
  11.     this.blogMapper.deleteBlog(blog.getId());
  12.   }
  13.   // 抛出一个RuntimeException
  14.   throw new RuntimeException("deleteBlogByCondition抛出一个异常");
  15.   // 单独调用时删除操作成功,因为没有事务
  16.   // 如果在一个事务中执行该方法,则会回滚
  17. }
  18. @Transactional
  19. public void insertAndDeleteBlogList1(List<Blog> blogList, BlogSearchParameter parameter) {
  20.   BlogSupportsTxService blogService =
  21.       this.applicationContext.getBean(BlogSupportsTxService.class);
  22.   // 插入数据
  23.   blogService.insertBlogList(blogList);
  24.   // 删除数据
  25.   blogService.deleteBlogByCondition(parameter);
  26.   // deleteBlogByCondition方法抛出异常之后,则insertAndDeleteBlogList1方法的操作会回滚
  27.   // 如果insertAndDeleteBlogList1方法在另一个事务中,则之前的事务操作都会回滚
  28. }
  29. @Transactional
  30. public void insertAndDeleteBlogList2(List<Blog> blogList, BlogSearchParameter parameter) {
  31.   BlogSupportsTxService blogService =
  32.       this.applicationContext.getBean(BlogSupportsTxService.class);
  33.   // 插入数据
  34.   blogService.insertBlogList(blogList);
  35.   // 删除数据
  36.   try {
  37.     blogService.deleteBlogByCondition(parameter);
  38.   } catch (Exception e) {
  39.     System.err.printf("Err:%s%n", e.getMessage());
  40.   }
  41.   System.out.println("继续插入数据");
  42.   // 继续插入数据
  43.   blogService.insertBlogList(blogList);
  44.   // deleteBlogByCondition方法抛出异常之后,会执行catch代码块,之后继续向下执行,
  45.   // 执行blogService.insertBlogList(blogList)方法之后,
  46.   // 在commit的时候检测到insertAndDeleteBlogList2方法rollback-only状态,会抛出异常:
  47.   // org.springframework.transaction.UnexpectedRollbackException:
  48.   // Transaction rolled back because it has been marked as rollback-only
  49. }
  50. public void insertAndDeleteBlogList3(List<Blog> blogList, BlogSearchParameter parameter) {
  51.   BlogSupportsTxService blogService =
  52.       this.applicationContext.getBean(BlogSupportsTxService.class);
  53.   // 插入数据
  54.   blogService.insertBlogList(blogList);
  55.   // 删除数据
  56.   blogService.deleteBlogByCondition(parameter);
  57.   // 由于insertAndDeleteBlogList3方法没有开启事务
  58.   // 插入和删除都会成功,但是deleteBlogByCondition(parameter)还是会抛出异常
  59. }
  60. public void insertAndDeleteBlogList4(List<Blog> blogList, BlogSearchParameter parameter) {
  61.   BlogSupportsTxService blogService =
  62.       this.applicationContext.getBean(BlogSupportsTxService.class);
  63.   // 插入数据
  64.   blogService.insertBlogList(blogList);
  65.   // 删除数据
  66.   try {
  67.     blogService.deleteBlogByCondition(parameter);
  68.   } catch (Exception e) {
  69.     System.err.printf("Err:%s%n", e.getMessage());
  70.   }
  71.   System.out.println("继续插入数据");
  72.   // 继续插入数据
  73.   blogService.insertBlogList(blogList);
  74.   // 由于insertAndDeleteBlogList4方法没有开启事务
  75.   // 插入和删除都会成功
  76. }
复制代码
NOT_SUPPORTED

Execute non-transactionally, suspend the current transaction if one exists.
在无事务状态下运行,如果当前已存在事务则挂起这个事务。
  1. @Transactional
  2. public void insertBlogList(List<Blog> blogList) {
  3.   for (Blog blog : blogList) {
  4.     this.blogMapper.insertBlog(blog);
  5.   }
  6. }
  7. @Transactional(propagation = Propagation.NOT_SUPPORTED)
  8. public void deleteBlogByCondition(BlogSearchParameter parameter) {
  9.   List<Blog> blogs = this.blogMapper.selectBlogByParameter(parameter);
  10.   for (Blog blog : blogs) {
  11.     this.blogMapper.deleteBlog(blog.getId());
  12.   }
  13.   // 抛出一个RuntimeException
  14.   throw new RuntimeException("deleteBlogByCondition抛出一个异常");
  15.   // 删除操作始终都会成功,但还是会抛出异常
  16. }
  17. @Transactional
  18. public void insertAndDeleteBlogList1(List<Blog> blogList, BlogSearchParameter parameter) {
  19.   BlogNotSupportedTxService blogService =
  20.       this.applicationContext.getBean(BlogNotSupportedTxService.class);
  21.   // 插入数据
  22.   blogService.insertBlogList(blogList);
  23.   // 删除数据
  24.   blogService.deleteBlogByCondition(parameter);
  25.   // blogService.deleteBlogByCondition(parameter)的删除操作成功
  26.   // deleteBlogByCondition方法抛出异常之后,则insertAndDeleteBlogList1方法的操作会回滚
  27.   // 如果insertAndDeleteBlogList1方法在另一个事务中,则之前的事务操作都会回滚
  28. }
  29. @Transactional
  30. public void insertAndDeleteBlogList2(List<Blog> blogList, BlogSearchParameter parameter) {
  31.   BlogNotSupportedTxService blogService =
  32.       this.applicationContext.getBean(BlogNotSupportedTxService.class);
  33.   // 插入数据
  34.   blogService.insertBlogList(blogList);
  35.   // 删除数据
  36.   try {
  37.     blogService.deleteBlogByCondition(parameter);
  38.   } catch (Exception e) {
  39.     System.err.printf("Err:%s%n", e.getMessage());
  40.   }
  41.   System.out.println("继续插入数据");
  42.   // 继续插入数据
  43.   blogService.insertBlogList(blogList);
  44.   // 插入数据和删除操作都会成功
  45. }
  46. public void insertAndDeleteBlogList3(List<Blog> blogList, BlogSearchParameter parameter) {
  47.   BlogNotSupportedTxService blogService =
  48.       this.applicationContext.getBean(BlogNotSupportedTxService.class);
  49.   // 插入数据
  50.   blogService.insertBlogList(blogList);
  51.   // 删除数据
  52.   blogService.deleteBlogByCondition(parameter);
  53.   // 插入数据和删除操作都会成功
  54.   // 但是会抛出异常
  55. }
  56. public void insertAndDeleteBlogList4(List<Blog> blogList, BlogSearchParameter parameter) {
  57.   BlogNotSupportedTxService blogService =
  58.       this.applicationContext.getBean(BlogNotSupportedTxService.class);
  59.   // 插入数据
  60.   blogService.insertBlogList(blogList);
  61.   // 删除数据
  62.   try {
  63.     blogService.deleteBlogByCondition(parameter);
  64.   } catch (Exception e) {
  65.     System.err.printf("Err:%s%n", e.getMessage());
  66.   }
  67.   System.out.println("继续插入数据");
  68.   // 继续插入数据
  69.   blogService.insertBlogList(blogList);
  70.   // 插入数据和删除操作都会成功
  71. }
复制代码
NEVER

Execute non-transactionally, throw an exception if a transaction exists.在无事务状态下运行,如果当前已存在事务,则抛出异常。
  1. @Transactional
  2. public void insertBlogList(List<Blog> blogList) {
  3.   for (Blog blog : blogList) {
  4.     this.blogMapper.insertBlog(blog);
  5.   }
  6. }
  7. @Transactional(propagation = Propagation.NEVER)
  8. public void deleteBlogByCondition(BlogSearchParameter parameter) {
  9.   List<Blog> blogs = this.blogMapper.selectBlogByParameter(parameter);
  10.   for (Blog blog : blogs) {
  11.     this.blogMapper.deleteBlog(blog.getId());
  12.   }
  13.   // 抛出一个RuntimeException
  14.   throw new RuntimeException("deleteBlogByCondition抛出一个异常");
  15. }
  16. @Transactional
  17. public void insertAndDeleteBlogList1(List<Blog> blogList, BlogSearchParameter parameter) {
  18.   BlogNeverTxService blogService =
  19.       this.applicationContext.getBean(BlogNeverTxService.class);
  20.   // 插入数据
  21.   blogService.insertBlogList(blogList);
  22.   // 删除数据
  23.   blogService.deleteBlogByCondition(parameter);
  24.   // 插入数据操作回滚
  25.   // 因为blogService.deleteBlogByCondition(parameter)检查到存在事务会抛出异常:
  26.   // org.springframework.transaction.IllegalTransactionStateException:
  27.   // Existing transaction found for transaction marked with propagation 'never'
  28. }
  29. @Transactional
  30. public void insertAndDeleteBlogList2(List<Blog> blogList, BlogSearchParameter parameter) {
  31.   BlogNeverTxService blogService =
  32.       this.applicationContext.getBean(BlogNeverTxService.class);
  33.   // 插入数据
  34.   blogService.insertBlogList(blogList);
  35.   // 删除数据
  36.   try {
  37.     blogService.deleteBlogByCondition(parameter);
  38.   } catch (Exception e) {
  39.     System.err.printf("Err:%s%n", e.getMessage());
  40.   }
  41.   System.out.println("继续插入数据");
  42.   // 继续插入数据
  43.   blogService.insertBlogList(blogList);
  44.   // 两次插入操作会成功
  45.   // 但是删除操作失败,因为blogService.deleteBlogByCondition(parameter)检查到存在事务会抛出异常:
  46.   // org.springframework.transaction.IllegalTransactionStateException:
  47.   // Existing transaction found for transaction marked with propagation 'never'
  48. }
  49. public void insertAndDeleteBlogList3(List<Blog> blogList, BlogSearchParameter parameter) {
  50.   BlogNeverTxService blogService =
  51.       this.applicationContext.getBean(BlogNeverTxService.class);
  52.   // 插入数据
  53.   blogService.insertBlogList(blogList);
  54.   // 删除数据
  55.   blogService.deleteBlogByCondition(parameter);
  56.   // 插入和删除都成功
  57.   // 但是会抛出异常
  58. }
  59. public void insertAndDeleteBlogList4(List<Blog> blogList, BlogSearchParameter parameter) {
  60.   BlogNeverTxService blogService =
  61.       this.applicationContext.getBean(BlogNeverTxService.class);
  62.   // 插入数据
  63.   blogService.insertBlogList(blogList);
  64.   // 删除数据
  65.   try {
  66.     blogService.deleteBlogByCondition(parameter);
  67.   } catch (Exception e) {
  68.     System.err.printf("Err:%s%n", e.getMessage());
  69.   }
  70.   System.out.println("继续插入数据");
  71.   // 继续插入数据
  72.   blogService.insertBlogList(blogList);
  73.   // 插入和删除都成功
  74. }
复制代码
NESTED

Execute within a nested transaction if a current transaction exists, behave like REQUIRED otherwise.
如果当前已存在事务,则嵌入到当前事务中运行,否则和REQUIRED效果一样。
  1. @Transactional(propagation = Propagation.NESTED)
  2. public void insertBlogList(List<Blog> blogList) {
  3.   for (Blog blog : blogList) {
  4.     this.blogMapper.insertBlog(blog);
  5.   }
  6. }
  7. @Transactional(propagation = Propagation.NESTED)
  8. public void deleteBlogByCondition(BlogSearchParameter parameter) {
  9.   List<Blog> blogs = this.blogMapper.selectBlogByParameter(parameter);
  10.   for (Blog blog : blogs) {
  11.     this.blogMapper.deleteBlog(blog.getId());
  12.   }
  13.   // 抛出一个RuntimeException
  14.   throw new RuntimeException("deleteBlogByCondition抛出一个异常");
  15. }
  16. @Transactional
  17. public void insertAndDeleteBlogList1(List<Blog> blogList, BlogSearchParameter parameter) {
  18.   BlogNestedTxService blogService =
  19.       this.applicationContext.getBean(BlogNestedTxService.class);
  20.   // 插入数据
  21.   blogService.insertBlogList(blogList);
  22.   // 删除数据
  23.   blogService.deleteBlogByCondition(parameter);
  24.   // 所有操作都会回滚
  25. }
  26. @Transactional
  27. public void insertAndDeleteBlogList2(List<Blog> blogList, BlogSearchParameter parameter) {
  28.   BlogNestedTxService blogService =
  29.       this.applicationContext.getBean(BlogNestedTxService.class);
  30.   // 插入数据
  31.   blogService.insertBlogList(blogList);
  32.   // 删除数据
  33.   try {
  34.     blogService.deleteBlogByCondition(parameter);
  35.   } catch (Exception e) {
  36.     System.err.printf("Err:%s%n", e.getMessage());
  37.   }
  38.   System.out.println("继续插入数据");
  39.   // 继续插入数据
  40.   blogService.insertBlogList(blogList);
  41.   // 前后两次插入操作成功,
  42.   // 中间的删除操作因为抛出异常,会回滚,
  43.   // 又因为blogService.deleteBlogByCondition(parameter)的异常被try...catch了,
  44.   // 没有抛到insertAndDeleteBlogList2中,所以insertAndDeleteBlogList2的操作可以成功提交
  45. }
  46. public void insertAndDeleteBlogList3(List<Blog> blogList, BlogSearchParameter parameter) {
  47.   BlogNestedTxService blogService =
  48.       this.applicationContext.getBean(BlogNestedTxService.class);
  49.   // 插入数据
  50.   blogService.insertBlogList(blogList);
  51.   // 删除数据
  52.   blogService.deleteBlogByCondition(parameter);
  53.   // 插入成功,删除回滚
  54. }
  55. public void insertAndDeleteBlogList4(List<Blog> blogList, BlogSearchParameter parameter) {
  56.   BlogNestedTxService blogService =
  57.       this.applicationContext.getBean(BlogNestedTxService.class);
  58.   // 插入数据
  59.   blogService.insertBlogList(blogList);
  60.   // 删除数据
  61.   try {
  62.     blogService.deleteBlogByCondition(parameter);
  63.   } catch (Exception e) {
  64.     System.err.printf("Err:%s%n", e.getMessage());
  65.   }
  66.   System.out.println("继续插入数据");
  67.   // 继续插入数据
  68.   blogService.insertBlogList(blogList);
  69.   // 插入成功,删除回滚
  70. }
复制代码
小结

本文通过示例介绍了spring-tx的七种事务传播级别,后续的文章将阅读源码,分析spring-tx的实现方式。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

张春

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表