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

这篇具有很好参考价值的文章主要介绍了spring-transaction源码分析(1)概述和事务传播级别。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

spring-tx概述

spring-tx包使用注解驱动和AOP通知将事务开启、提交/回滚、以及复杂的传播机制封装了起来,开发者不再需要编写事务管理的代码,而是可以只关注自己的业务逻辑。

本文将简单介绍spring-tx使用步骤以及七种事务传播级别。

后续文章会阅读源码,深入分析spring-tx aop通知、七种事务传播级别以及事务开启/提交/回滚的实现方式。

使用步骤

  1. 导入spring-tx依赖
  2. 使用@EnableTransactionManagement注解为应用开启事务支持
  3. 向spring容器注入一个TransactionManager实现,一般使用DataSourceTransactionManager类
  4. 在需要事务的业务方法上标注@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. 支持当前存在的事务,如果当前没有事务,则在无事务状态下运行。

    For transaction managers with transaction synchronization, SUPPORTS is slightly different from 
    no transaction at all, as it defines a transaction scope that synchronization will apply for.
    As a consequence, the same resources (JDBC Connection, Hibernate Session, etc) will be shared 
    for the entire specified scope. Note that this depends on the actual synchronization configuration 
    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添加的参数不同而已,此处记录一下这几个方法:

public void insertBlogList(List<Blog> blogList) {
  for (int i = 0; i < blogList.size(); i++) {
    this.blogMapper.insertBlog(blogList.get(i));
  }
}

public void deleteBlogByCondition(BlogSearchParameter parameter) {
  List<Blog> blogs = this.blogMapper.selectBlogByParameter(parameter);
  for (Blog blog : blogs) {
    this.blogMapper.deleteBlog(blog.getId());
  }
  // 抛出一个RuntimeException
  throw new RuntimeException("deleteBlogByCondition抛出一个异常");
}

public void insertAndDeleteBlogList1(List<Blog> blogList, BlogSearchParameter parameter) {

  // 这里从spring容器获取service对象,避免事务失效
  BlogRequiredTxService blogService =
      this.applicationContext.getBean(BlogRequiredTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  blogService.deleteBlogByCondition(parameter);
}

public void insertAndDeleteBlogList2(List<Blog> blogList, BlogSearchParameter parameter) {

  BlogRequiredTxService blogService =
      this.applicationContext.getBean(BlogRequiredTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  try {
    blogService.deleteBlogByCondition(parameter);
  } catch (Exception e) {
    System.err.printf("Err:%s%n", e.getMessage());
  }

  System.out.println("继续插入数据");

  // 继续插入数据
  blogService.insertBlogList(blogList);
}

public void insertAndDeleteBlogList3(List<Blog> blogList, BlogSearchParameter parameter) {

  BlogRequiredTxService blogService =
      this.applicationContext.getBean(BlogRequiredTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  blogService.deleteBlogByCondition(parameter);
}

public void insertAndDeleteBlogList4(List<Blog> blogList, BlogSearchParameter parameter) {

  BlogRequiredTxService blogService =
      this.applicationContext.getBean(BlogRequiredTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  try {
    blogService.deleteBlogByCondition(parameter);
  } catch (Exception e) {
    System.err.printf("Err:%s%n", e.getMessage());
  }

  System.out.println("继续插入数据");

  // 继续插入数据
  blogService.insertBlogList(blogList);
}

传播级别详细说明

REQUIRED

Support a current transaction, create a new one if none exists.

支持当前存在的事务,如果当前没有事务,则新创建一个。默认的传播级别。

@Transactional(propagation = Propagation.REQUIRED)
public void insertBlogList(List<Blog> blogList) {
  for (int i = 0; i < blogList.size(); i++) {
    this.blogMapper.insertBlog(blogList.get(i));
  }
}

@Transactional(propagation = Propagation.REQUIRED)
public void deleteBlogByCondition(BlogSearchParameter parameter) {
  List<Blog> blogs = this.blogMapper.selectBlogByParameter(parameter);
  for (Blog blog : blogs) {
    this.blogMapper.deleteBlog(blog.getId());
  }
  // 抛出一个RuntimeException
  throw new RuntimeException("deleteBlogByCondition抛出一个异常");

  // 如果调用方法前,没有事务,则delete操作都会回滚
  // 如果调用方法前,已经存在事务,则之前的事务操作都会回滚
}

@Transactional(propagation = Propagation.REQUIRED)
public void insertAndDeleteBlogList1(List<Blog> blogList, BlogSearchParameter parameter) {

  BlogRequiredTxService blogService =
      this.applicationContext.getBean(BlogRequiredTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  blogService.deleteBlogByCondition(parameter);

  // deleteBlogByCondition方法抛出异常之后,则insertAndDeleteBlogList1方法的操作会回滚
  // 如果insertAndDeleteBlogList1方法在另一个事务中,则之前的事务操作都会回滚
}

@Transactional(propagation = Propagation.REQUIRED)
public void insertAndDeleteBlogList2(List<Blog> blogList, BlogSearchParameter parameter) {

  BlogRequiredTxService blogService =
      this.applicationContext.getBean(BlogRequiredTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  try {
    blogService.deleteBlogByCondition(parameter);
  } catch (Exception e) {
    System.err.printf("Err:%s%n", e.getMessage());
  }

  System.out.println("继续插入数据");

  // 继续插入数据
  blogService.insertBlogList(blogList);

  // deleteBlogByCondition方法抛出异常之后,会执行catch代码块,之后继续向下执行,
  // 执行blogService.insertBlogList(blogList)方法之后,
  // 在commit的时候检测到insertAndDeleteBlogList2方法rollback-only状态,会抛出异常:
  // org.springframework.transaction.UnexpectedRollbackException: 
  // Transaction rolled back because it has been marked as rollback-only
}

public void insertAndDeleteBlogList3(List<Blog> blogList, BlogSearchParameter parameter) {

  BlogRequiredTxService blogService =
      this.applicationContext.getBean(BlogRequiredTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  blogService.deleteBlogByCondition(parameter);

  // 由于insertAndDeleteBlogList3方法没有标注Transactional注解:
  // blogService.insertBlogList(blogList)方法插入的数据会提交保存下来
  // blogService.deleteBlogByCondition(parameter)方法的删除操作会回滚
}

public void insertAndDeleteBlogList4(List<Blog> blogList, BlogSearchParameter parameter) {

  BlogRequiredTxService blogService =
      this.applicationContext.getBean(BlogRequiredTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  try {
    blogService.deleteBlogByCondition(parameter);
  } catch (Exception e) {
    System.err.printf("Err:%s%n", e.getMessage());
  }

  System.out.println("继续插入数据");

  // 继续插入数据
  blogService.insertBlogList(blogList);

  // 由于insertAndDeleteBlogList3方法没有标注Transactional注解:
  // blogService.insertBlogList(blogList)方法插入的数据会提交保存下来
  // blogService.deleteBlogByCondition(parameter)方法的删除操作会回滚
  // 之后会继续执行blogService.insertBlogList(blogList)再插入数据
}

REQUIRES_NEW

Create a new transaction, and suspend the current transaction if one exists.

创建新事务,如果当前已存在事务则挂起这个事务,再打开一个新的数据库连接创建新事务。

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void insertBlogList(List<Blog> blogList) {
  for (Blog blog : blogList) {
    this.blogMapper.insertBlog(blog);
  }
  try {
    TimeUnit.SECONDS.sleep(15);
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void deleteBlogByCondition(BlogSearchParameter parameter) {
  List<Blog> blogs = this.blogMapper.selectBlogByParameter(parameter);
  for (Blog blog : blogs) {
    this.blogMapper.deleteBlog(blog.getId());
  }
  // 抛出一个RuntimeException
  throw new RuntimeException("deleteBlogByCondition抛出一个异常");

  // 只会回滚delete操作,因为该方法是新创建的事务
}

@Transactional
public void insertAndDeleteBlogList1(List<Blog> blogList, BlogSearchParameter parameter) {

  BlogRequiresNewTxService blogService =
      this.applicationContext.getBean(BlogRequiresNewTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  blogService.deleteBlogByCondition(parameter);

  // blogService.insertBlogList(blogList)成功
  // blogService.deleteBlogByCondition(parameter)会回滚
  // 同时insertAndDeleteBlogList1中的事务也会回滚

  // 如果使用show processlist查看客户端进程,
  // 可以看到insertBlogList和deleteBlogByCondition方法创建了新的数据库连接
}

@Transactional
public void insertAndDeleteBlogList2(List<Blog> blogList, BlogSearchParameter parameter) {

  BlogRequiresNewTxService blogService =
      this.applicationContext.getBean(BlogRequiresNewTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  try {
    blogService.deleteBlogByCondition(parameter);
  } catch (Exception e) {
    System.err.printf("Err:%s%n", e.getMessage());
  }

  System.out.println("继续插入数据");

  // 继续插入数据
  blogService.insertBlogList(blogList);

  // blogService.insertBlogList(blogList)成功
  // blogService.deleteBlogByCondition(parameter)会回滚
  // 此时insertAndDeleteBlogList1中的事务不会回滚,因为deleteBlogByCondition(parameter)的异常被"吞掉了"
  // 后续的blogService.insertBlogList(blogList)也会成功
}

public void insertAndDeleteBlogList3(List<Blog> blogList, BlogSearchParameter parameter) {

  BlogRequiresNewTxService blogService =
      this.applicationContext.getBean(BlogRequiresNewTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  blogService.deleteBlogByCondition(parameter);

  // blogService.insertBlogList(blogList)成功
  // blogService.deleteBlogByCondition(parameter)会回滚
}

public void insertAndDeleteBlogList4(List<Blog> blogList, BlogSearchParameter parameter) {

  BlogRequiresNewTxService blogService =
      this.applicationContext.getBean(BlogRequiresNewTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  try {
    blogService.deleteBlogByCondition(parameter);
  } catch (Exception e) {
    System.err.printf("Err:%s%n", e.getMessage());
  }

  System.out.println("继续插入数据");

  // 继续插入数据
  blogService.insertBlogList(blogList);

  // blogService.insertBlogList(blogList)成功
  // blogService.deleteBlogByCondition(parameter)会回滚
  // 后续的blogService.insertBlogList(blogList)也会成功
}

MANDATORY

Support a current transaction, throw an exception if none exists.

支持当前存在的事务,如果当前没有事务,则抛出异常。

@Transactional(propagation = Propagation.MANDATORY)
public void insertBlogList(List<Blog> blogList) {
  for (Blog blog : blogList) {
    this.blogMapper.insertBlog(blog);
  }

  // 单独调用此方法时抛错:
  // org.springframework.transaction.IllegalTransactionStateException:
  // No existing transaction found for transaction marked with propagation 'mandatory'
}

@Transactional(propagation = Propagation.MANDATORY)
public void deleteBlogByCondition(BlogSearchParameter parameter) {
  List<Blog> blogs = this.blogMapper.selectBlogByParameter(parameter);
  for (Blog blog : blogs) {
    this.blogMapper.deleteBlog(blog.getId());
  }
  // 抛出一个RuntimeException
  throw new RuntimeException("deleteBlogByCondition抛出一个异常");

  // 单独调用此方法时抛错:
  // org.springframework.transaction.IllegalTransactionStateException:
  // No existing transaction found for transaction marked with propagation 'mandatory'
}

@Transactional
public void insertAndDeleteBlogList1(List<Blog> blogList, BlogSearchParameter parameter) {

  BlogMandatoryTxService blogService =
      this.applicationContext.getBean(BlogMandatoryTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  blogService.deleteBlogByCondition(parameter);

  // deleteBlogByCondition方法抛出异常之后,则insertAndDeleteBlogList1方法的操作会回滚
  // 如果insertAndDeleteBlogList1方法在另一个事务中,则之前的事务操作都会回滚
}

@Transactional
public void insertAndDeleteBlogList2(List<Blog> blogList, BlogSearchParameter parameter) {

  BlogMandatoryTxService blogService =
      this.applicationContext.getBean(BlogMandatoryTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  try {
    blogService.deleteBlogByCondition(parameter);
  } catch (Exception e) {
    System.err.printf("Err:%s%n", e.getMessage());
  }

  System.out.println("继续插入数据");

  // 继续插入数据
  blogService.insertBlogList(blogList);

  // deleteBlogByCondition方法抛出异常之后,会执行catch代码块,之后继续向下执行,
  // 执行blogService.insertBlogList(blogList)方法之后,
  // 在commit的时候检测到insertAndDeleteBlogList2方法rollback-only状态,会抛出异常:
  // org.springframework.transaction.UnexpectedRollbackException: 
  // Transaction rolled back because it has been marked as rollback-only
}

public void insertAndDeleteBlogList3(List<Blog> blogList, BlogSearchParameter parameter) {

  BlogMandatoryTxService blogService =
      this.applicationContext.getBean(BlogMandatoryTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  blogService.deleteBlogByCondition(parameter);

  // 抛错:
  // org.springframework.transaction.IllegalTransactionStateException:
  // No existing transaction found for transaction marked with propagation 'mandatory'
}

public void insertAndDeleteBlogList4(List<Blog> blogList, BlogSearchParameter parameter) {

  BlogMandatoryTxService blogService =
      this.applicationContext.getBean(BlogMandatoryTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  try {
    blogService.deleteBlogByCondition(parameter);
  } catch (Exception e) {
    System.err.printf("Err:%s%n", e.getMessage());
  }

  System.out.println("继续插入数据");

  // 继续插入数据
  blogService.insertBlogList(blogList);

  // 抛错:
  // org.springframework.transaction.IllegalTransactionStateException:
  // No existing transaction found for transaction marked with propagation 'mandatory'
}

SUPPORTS

Support a current transaction, execute non-transactionally if none exists.

支持当前存在的事务,如果当前没有事务,则在无事务状态下运行。

@Transactional(propagation = Propagation.SUPPORTS)
public void insertBlogList(List<Blog> blogList) {
  for (Blog blog : blogList) {
    this.blogMapper.insertBlog(blog);
  }
}

@Transactional(propagation = Propagation.SUPPORTS)
public void deleteBlogByCondition(BlogSearchParameter parameter) {
  List<Blog> blogs = this.blogMapper.selectBlogByParameter(parameter);
  for (Blog blog : blogs) {
    this.blogMapper.deleteBlog(blog.getId());
  }
  // 抛出一个RuntimeException
  throw new RuntimeException("deleteBlogByCondition抛出一个异常");

  // 单独调用时删除操作成功,因为没有事务
  // 如果在一个事务中执行该方法,则会回滚
}

@Transactional
public void insertAndDeleteBlogList1(List<Blog> blogList, BlogSearchParameter parameter) {

  BlogSupportsTxService blogService =
      this.applicationContext.getBean(BlogSupportsTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  blogService.deleteBlogByCondition(parameter);

  // deleteBlogByCondition方法抛出异常之后,则insertAndDeleteBlogList1方法的操作会回滚
  // 如果insertAndDeleteBlogList1方法在另一个事务中,则之前的事务操作都会回滚
}

@Transactional
public void insertAndDeleteBlogList2(List<Blog> blogList, BlogSearchParameter parameter) {

  BlogSupportsTxService blogService =
      this.applicationContext.getBean(BlogSupportsTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  try {
    blogService.deleteBlogByCondition(parameter);
  } catch (Exception e) {
    System.err.printf("Err:%s%n", e.getMessage());
  }

  System.out.println("继续插入数据");

  // 继续插入数据
  blogService.insertBlogList(blogList);

  // deleteBlogByCondition方法抛出异常之后,会执行catch代码块,之后继续向下执行,
  // 执行blogService.insertBlogList(blogList)方法之后,
  // 在commit的时候检测到insertAndDeleteBlogList2方法rollback-only状态,会抛出异常:
  // org.springframework.transaction.UnexpectedRollbackException: 
  // Transaction rolled back because it has been marked as rollback-only
}

public void insertAndDeleteBlogList3(List<Blog> blogList, BlogSearchParameter parameter) {

  BlogSupportsTxService blogService =
      this.applicationContext.getBean(BlogSupportsTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  blogService.deleteBlogByCondition(parameter);

  // 由于insertAndDeleteBlogList3方法没有开启事务
  // 插入和删除都会成功,但是deleteBlogByCondition(parameter)还是会抛出异常
}

public void insertAndDeleteBlogList4(List<Blog> blogList, BlogSearchParameter parameter) {

  BlogSupportsTxService blogService =
      this.applicationContext.getBean(BlogSupportsTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  try {
    blogService.deleteBlogByCondition(parameter);
  } catch (Exception e) {
    System.err.printf("Err:%s%n", e.getMessage());
  }

  System.out.println("继续插入数据");

  // 继续插入数据
  blogService.insertBlogList(blogList);

  // 由于insertAndDeleteBlogList4方法没有开启事务
  // 插入和删除都会成功
}

NOT_SUPPORTED

Execute non-transactionally, suspend the current transaction if one exists.

在无事务状态下运行,如果当前已存在事务则挂起这个事务。

@Transactional
public void insertBlogList(List<Blog> blogList) {
  for (Blog blog : blogList) {
    this.blogMapper.insertBlog(blog);
  }
}

@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void deleteBlogByCondition(BlogSearchParameter parameter) {
  List<Blog> blogs = this.blogMapper.selectBlogByParameter(parameter);
  for (Blog blog : blogs) {
    this.blogMapper.deleteBlog(blog.getId());
  }
  // 抛出一个RuntimeException
  throw new RuntimeException("deleteBlogByCondition抛出一个异常");

  // 删除操作始终都会成功,但还是会抛出异常
}

@Transactional
public void insertAndDeleteBlogList1(List<Blog> blogList, BlogSearchParameter parameter) {

  BlogNotSupportedTxService blogService =
      this.applicationContext.getBean(BlogNotSupportedTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  blogService.deleteBlogByCondition(parameter);

  // blogService.deleteBlogByCondition(parameter)的删除操作成功
  // deleteBlogByCondition方法抛出异常之后,则insertAndDeleteBlogList1方法的操作会回滚
  // 如果insertAndDeleteBlogList1方法在另一个事务中,则之前的事务操作都会回滚
}

@Transactional
public void insertAndDeleteBlogList2(List<Blog> blogList, BlogSearchParameter parameter) {

  BlogNotSupportedTxService blogService =
      this.applicationContext.getBean(BlogNotSupportedTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  try {
    blogService.deleteBlogByCondition(parameter);
  } catch (Exception e) {
    System.err.printf("Err:%s%n", e.getMessage());
  }

  System.out.println("继续插入数据");

  // 继续插入数据
  blogService.insertBlogList(blogList);

  // 插入数据和删除操作都会成功
}

public void insertAndDeleteBlogList3(List<Blog> blogList, BlogSearchParameter parameter) {

  BlogNotSupportedTxService blogService =
      this.applicationContext.getBean(BlogNotSupportedTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  blogService.deleteBlogByCondition(parameter);

  // 插入数据和删除操作都会成功
  // 但是会抛出异常
}

public void insertAndDeleteBlogList4(List<Blog> blogList, BlogSearchParameter parameter) {

  BlogNotSupportedTxService blogService =
      this.applicationContext.getBean(BlogNotSupportedTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  try {
    blogService.deleteBlogByCondition(parameter);
  } catch (Exception e) {
    System.err.printf("Err:%s%n", e.getMessage());
  }

  System.out.println("继续插入数据");

  // 继续插入数据
  blogService.insertBlogList(blogList);

  // 插入数据和删除操作都会成功
}

NEVER

Execute non-transactionally, throw an exception if a transaction exists.在无事务状态下运行,如果当前已存在事务,则抛出异常。

@Transactional
public void insertBlogList(List<Blog> blogList) {
  for (Blog blog : blogList) {
    this.blogMapper.insertBlog(blog);
  }
}

@Transactional(propagation = Propagation.NEVER)
public void deleteBlogByCondition(BlogSearchParameter parameter) {
  List<Blog> blogs = this.blogMapper.selectBlogByParameter(parameter);
  for (Blog blog : blogs) {
    this.blogMapper.deleteBlog(blog.getId());
  }
  // 抛出一个RuntimeException
  throw new RuntimeException("deleteBlogByCondition抛出一个异常");
}

@Transactional
public void insertAndDeleteBlogList1(List<Blog> blogList, BlogSearchParameter parameter) {

  BlogNeverTxService blogService =
      this.applicationContext.getBean(BlogNeverTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  blogService.deleteBlogByCondition(parameter);

  // 插入数据操作回滚
  // 因为blogService.deleteBlogByCondition(parameter)检查到存在事务会抛出异常:
  // org.springframework.transaction.IllegalTransactionStateException:
  // Existing transaction found for transaction marked with propagation 'never'
}

@Transactional
public void insertAndDeleteBlogList2(List<Blog> blogList, BlogSearchParameter parameter) {

  BlogNeverTxService blogService =
      this.applicationContext.getBean(BlogNeverTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  try {
    blogService.deleteBlogByCondition(parameter);
  } catch (Exception e) {
    System.err.printf("Err:%s%n", e.getMessage());
  }

  System.out.println("继续插入数据");

  // 继续插入数据
  blogService.insertBlogList(blogList);

  // 两次插入操作会成功
  // 但是删除操作失败,因为blogService.deleteBlogByCondition(parameter)检查到存在事务会抛出异常:
  // org.springframework.transaction.IllegalTransactionStateException:
  // Existing transaction found for transaction marked with propagation 'never'
}

public void insertAndDeleteBlogList3(List<Blog> blogList, BlogSearchParameter parameter) {

  BlogNeverTxService blogService =
      this.applicationContext.getBean(BlogNeverTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  blogService.deleteBlogByCondition(parameter);

  // 插入和删除都成功
  // 但是会抛出异常
}

public void insertAndDeleteBlogList4(List<Blog> blogList, BlogSearchParameter parameter) {

  BlogNeverTxService blogService =
      this.applicationContext.getBean(BlogNeverTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  try {
    blogService.deleteBlogByCondition(parameter);
  } catch (Exception e) {
    System.err.printf("Err:%s%n", e.getMessage());
  }

  System.out.println("继续插入数据");

  // 继续插入数据
  blogService.insertBlogList(blogList);

  // 插入和删除都成功
}

NESTED

Execute within a nested transaction if a current transaction exists, behave like REQUIRED otherwise.

如果当前已存在事务,则嵌入到当前事务中运行,否则和REQUIRED效果一样。

@Transactional(propagation = Propagation.NESTED)
public void insertBlogList(List<Blog> blogList) {
  for (Blog blog : blogList) {
    this.blogMapper.insertBlog(blog);
  }
}

@Transactional(propagation = Propagation.NESTED)
public void deleteBlogByCondition(BlogSearchParameter parameter) {
  List<Blog> blogs = this.blogMapper.selectBlogByParameter(parameter);
  for (Blog blog : blogs) {
    this.blogMapper.deleteBlog(blog.getId());
  }
  // 抛出一个RuntimeException
  throw new RuntimeException("deleteBlogByCondition抛出一个异常");
}

@Transactional
public void insertAndDeleteBlogList1(List<Blog> blogList, BlogSearchParameter parameter) {

  BlogNestedTxService blogService =
      this.applicationContext.getBean(BlogNestedTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  blogService.deleteBlogByCondition(parameter);

  // 所有操作都会回滚
}

@Transactional
public void insertAndDeleteBlogList2(List<Blog> blogList, BlogSearchParameter parameter) {

  BlogNestedTxService blogService =
      this.applicationContext.getBean(BlogNestedTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  try {
    blogService.deleteBlogByCondition(parameter);
  } catch (Exception e) {
    System.err.printf("Err:%s%n", e.getMessage());
  }

  System.out.println("继续插入数据");

  // 继续插入数据
  blogService.insertBlogList(blogList);

  // 前后两次插入操作成功,
  // 中间的删除操作因为抛出异常,会回滚,
  // 又因为blogService.deleteBlogByCondition(parameter)的异常被try...catch了,
  // 没有抛到insertAndDeleteBlogList2中,所以insertAndDeleteBlogList2的操作可以成功提交
}

public void insertAndDeleteBlogList3(List<Blog> blogList, BlogSearchParameter parameter) {

  BlogNestedTxService blogService =
      this.applicationContext.getBean(BlogNestedTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  blogService.deleteBlogByCondition(parameter);

  // 插入成功,删除回滚
}

public void insertAndDeleteBlogList4(List<Blog> blogList, BlogSearchParameter parameter) {

  BlogNestedTxService blogService =
      this.applicationContext.getBean(BlogNestedTxService.class);

  // 插入数据
  blogService.insertBlogList(blogList);

  // 删除数据
  try {
    blogService.deleteBlogByCondition(parameter);
  } catch (Exception e) {
    System.err.printf("Err:%s%n", e.getMessage());
  }

  System.out.println("继续插入数据");

  // 继续插入数据
  blogService.insertBlogList(blogList);

  // 插入成功,删除回滚
}

小结

本文通过示例介绍了spring-tx的七种事务传播级别,后续的文章将阅读源码,分析spring-tx的实现方式。文章来源地址https://www.toymoban.com/news/detail-434848.html

到了这里,关于spring-transaction源码分析(1)概述和事务传播级别的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring使用@Transactional 管理事务,Java事务详解。

    B站视频:https://www.bilibili.com/video/BV1eV411u7cg 技术文档:https://d9bp4nr5ye.feishu.cn/wiki/HX50wdHFyiFoLrkfEAAcTBdinvh 简单来说事务就是一组对数据库的操作 要么都成功,要么都失败。 事务要保证可靠性,必须具备四个特性:ACID。 A:原子性:事务是一个原子操作单元,要么完全执行,要么

    2024年02月11日
    浏览(31)
  • Spring @Transactional事务传播机制详解

    我们日常工作中极少使用事务传播级别,单纯只是使用事务和rollbackfor抛出异常来解决事务问题,但其实我们很多时候使用的是不正确的,或者说会造成事务粒度过大,本文详解一下事务传播级别,也让自己更好地处理事务问题。 1.什么是事务传播机制? 举个栗子,方法A是一

    2024年02月14日
    浏览(42)
  • Spring——事务注解@Transactional【建议收藏】

    在某些业务场景下,如果一个请求中,需要同时写入多张表的数据或者执行多条sql,为了保证操作的原子性(要么同时成功,要么同时失败),避免数据不一致的情况,我们一般都会用到事务;Spring框架下,我们经常会使用@Transactional注解来管理事务; 本篇介绍Spring的事务注

    2024年02月03日
    浏览(48)
  • Spring 事务(编程式事务、声明式事务@Transactional、事务隔离级别、事务传播机制)

    本篇重点总结: 在 Spring 项目中使用事务,有两种方式:编程式手动操作和声明式自动提交,声明式自动提交使用最多,只需要在方法上添加注解 @Transactional 设置事务的隔离级别 @Transactional(isolation = Isolation.SERIALIZABLE),Spring 中的事务隔离级别有5种 设置事务的传播机制 @Tra

    2024年02月03日
    浏览(43)
  • Spring源码分析(五) 事务全流程分析

    @Transactional 注解的属性信息 name 当在配置文件中有多个 TransactionManager , 可以用该属性指定选择哪个事务管理器 propagation 事务的传播行为,默认值为 REQUIRED。 isolation 事务的隔离度,默认值采用 DEFAULT。 timeout 事务的超时时间,默认值为-1。如果超过该时间限制但事务还没有完

    2024年02月07日
    浏览(36)
  • 【spring(四)】Spring事务管理和@Transactional注解

    🌈键盘敲烂,年薪30万🌈 目录 Spring中的事务管理 问题抛出: 解决方案: @Transactional注解: rollbackFor属性: propagation属性: 应用: 📕总结 知识回顾: ❓什么是事务 事务是对数据操作的集合,它是数据操作的最小执行单位,也就是说,要么一个事务中操作全部执行完毕,

    2024年01月17日
    浏览(49)
  • Spring 声明式事务 @Transactional(基本使用)

            声明式事务的实现很简单,只需要在需要事务的⽅法上添加 @Transactional 注解就可以实现了.⽆需⼿动开启事务和提交事务,进⼊⽅法时⾃动开启事务,⽅法执⾏完会⾃动提交事务,如果中途发⽣了 没有处理的异常会⾃动回滚事务.         废话不多说,直接看代码实现,

    2024年01月23日
    浏览(49)
  • 【JavaEE】Spring事务-事务的基本介绍-事务的实现-@Transactional基本介绍和使用

    【JavaEE】Spring 事务(1) 比如跟钱相关的两个操作: 第一步操作:小马卡里 - 100元 第二步操作:老马卡里 + 100元 这就是一个事务,捆在一起的一组行为,就是事务 而它能保证的是,这个行为的原子性,一致性,隔离性,持久性: 两个操作都成功 两个操作都失败 要么一起成

    2024年02月11日
    浏览(43)
  • 【JavaEE】Spring事务-@Transactional参数介绍-事务的隔离级别以及传播机制

    【JavaEE】Spring 事务(2) 参数 作用 value 当配置了多个事务管理器时,可以使用该属性指定选择哪个事务管理器 transactionManager 当配置了多个事务管理器时,可以使用该属性指定选择哪个事务管理器 isolation 事务的隔离级别.默认值为solation.DEFAULT propagation 事务的传播机制,默认值

    2024年02月10日
    浏览(49)
  • Spring5学习随笔-事务属性详解(@Transactional)

    学习视频:【孙哥说Spring5:从设计模式到基本应用到应用级底层分析,一次深入浅出的Spring全探索。学不会Spring?只因你未遇见孙哥】 事务是 保证业务操作完整性的一种数据库机制 事务的4特点:ACID A 原子性 C 一致性 I 隔离性 D 持久性 JDBC: Connection.setAutoCommit(false) Connect

    2024年02月05日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包