spring-transaction源码分析(1)概述和事务传播级别
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. 支持当前存在的事务,如果当前没有事务,则在无事务状态下运行。
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的实现方式。
spring-transaction源码分析(1)概述和事务传播级别的更多相关文章
- spring transaction源码分析--事务架构
1. 引言 事务特性 事务是并发控制的单元,是用户定义的一个操作序列.这些操作要么都做,要么都不做,是一个不可分割的工作单位.通过事务将逻辑相关的一组操作绑定在一起,以便服务器 保持数据的完整性.事 ...
- Spring Security 源码分析 --- WebSecurity
概述 spring security 源码分析系列文章. 源码分析 我们想一下,我们使用 ss 框架的步骤是怎么样的. @Configuration @EnableWebSecurity @Enabl ...
- 精尽Spring MVC源码分析 - WebApplicationContext 容器的初始化
该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...
- 精尽Spring Boot源码分析 - 序言
该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...
- 精尽Spring Boot源码分析 - Jar 包的启动实现
该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...
- 精尽Spring Boot源码分析 - SpringApplication 启动类的启动过程
该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...
- 精尽Spring Boot源码分析 - 内嵌Tomcat容器的实现
该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...
- 精尽Spring Boot源码分析 - 支持外部 Tomcat 容器的实现
该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...
- 精尽Spring Boot源码分析 - 剖析 @SpringBootApplication 注解
该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...
- 精尽Spring Boot源码分析 - Condition 接口的扩展
该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...
随机推荐
- 韩国国民搜索 NAVER:为 AI 平台引入存储方案 JuiceFS
NAVER 是一家多元化的互联网公司,拥有韩国最大的搜索引擎并在人工智能.自动驾驶等高科技领域积极投入. 在搭建 AI 平台时,NAVER 评估了公有云平台的存储产品.Alluxio 以及高性能专用存 ...
- Python——第二章:字符串操作——格式化
1. 字符串的格式化问题 举例:要按照如下格式输出一句话 我叫xxx, 我住在xxxx, 我今年xx岁, 我喜欢做xxxxx 这里首先引入占位符概念: %s 占位字符串%d 占位整数%f 占位小数 因 ...
- 技本功|Hive优化之监控(三)
Hive是大数据领域常用的组件之一,主要是大数据离线数仓的运算,关于Hive的性能调优在日常工作和面试中是经常涉及的一个点,因此掌握一些Hive调优是必不可少的技能.影响Hive效率的主要有数据倾斜. ...
- 如何在GitHub正确提PR(Pull Requests),给喜欢的开源项目贡献代码
最好的中文TTS项目Bert-vits2更新了中文特化分支,但可能由于时间仓促,代码中存在不少的bug,作为普通用户,有的时候也想为自己喜欢的开源项目做一点点贡献,帮助作者修改一些简单的bug,那么该 ...
- 全网最全的华为ensp数通设备命令全集
[命令] display history-command [视图]所有视图 [参数]无 [描述] display history-command 命令用来显示当 前用户曾键入的最后 10 条命令.用户 ...
- 文心一言 VS 讯飞星火 VS chatgpt (43)-- 算法导论5.4 7题
七.为使特征序列长度的下界变得更精确,请说明在 n 次硬币的公平抛掷中,不出现比Ign - 2lglgn 更长的连续正面特征序列的概率小于 1/n. 文心一言: 在 n 次硬币的公平抛掷中,每个硬币正 ...
- 了解库开发,我们从STM32标准库开发学起
摘要:从STM32新建工程.编译下载程序出发,让新手由浅入深,尽享STM32标准库开发的乐趣. 自从CubeMX等图像配置软件的出现,同学们往往点几下鼠标就解决了单片机的配置问题.对于追求开发速度的业 ...
- 经验说丨华为云视频Cloud Native架构下实践
摘要:来自华为云直播的段亮详细介绍华为云视频在Cloud Native的转型实践中遇到的问题.挑战以及解决之道. 随着云基础设施服务以及边缘计算技术的发展,Cloud Native,即云原生,架构理念 ...
- 案例集锦|科技赋能,华为云GaussDB助千行百业数字化转型
当下,全社会驶入数字化转型快车道,以科技赋能.智慧转型为主旨的数字生态推动着千行百业的变革.数据库作为企业核心数据底座,华为云提供了安全可靠的云原生底座和一站式上云解决方案.其中华为云GaussDB覆 ...
- 一文带你了解EiPaaS和EiPaaS的国际趋势
摘要:EiPaaS (Enterprise Integration Platform as a Service) 是企业级的集成平台和服务. 本文分享自华为云社区<初识EiPaaS和EiPaaS ...