Spring Boot 入门之路(13)--- Spring Boot 中实现事务管理

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/Geffin/article/details/100603660

1 前言

我们都知道,Spring 中的事务管理有编程式和声明式两种方式。其中,编程式事务是通过编码方式实现事务的,而声明式事务基于 AOP。由于声明式事务将具体业务逻辑与事务处理解耦,故其的应用范围较广。本文将介绍基于 @Transactional 注解的声明式事务实现形式。

2 注意事项

  1. 在默认配置的情况下,Spring 只会回滚继承自 RuntimeException 的异常或者 Error。
  2. 只有应用到 public 方法,@Transactional 注解才会生效。

这里我简单介绍一下 Java 的异常分类。其中 Throwable 是所有异常的根,而 Throwable 又可以分为 Error 和 Exception 两类。另外,Exception 内部也可分为两类,一为 Checked Exception,即可检查的异常,也称编译异常,这种我们必须使用 try-catch 去处理,另一类为 RuntimeException,即运行时异常,这种异常由虚拟机接管,我们可以不用处理。

3 最简单的使用

想要使用 Spring Boot 中的事务管理,只需在方法上加上 @Transactional 注解。

package edu.szu.test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import edu.szu.test.entity.Book;
import edu.szu.test.service.BookService;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {TestApplication.class})
public class MyTest {
	
	@Autowired
	BookService bookService;
	
	@Test
    public void test(){
		Book book = new Book();
		book.setName("Tony1");
		book.setPrice((float)13);
		
		bookService.insert(book);
		
		int i = 1/0;
	}
	
}

我们先不使用 @Transactional 注解,随意插入一条数据,可以看到虽然后面我们程序出现了一个错误,但前面的数据还是已经插入了数据库。

在这里插入图片描述
现在我们尝试实现 Spring Boot 中的事务管理,在方法前加上 @Transactional 注解,看看数据是否还会插入数据库?

package edu.szu.test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;

import edu.szu.test.entity.Book;
import edu.szu.test.service.BookService;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {TestApplication.class})
public class MyTest {
	
	@Autowired
	BookService bookService;
	
	@Test
	@Transactional
    public void test(){
		Book book = new Book();
		book.setName("Tony2");
		book.setPrice((float)14);
		
		bookService.insert(book);
		
		int i = 1/0;
	}
	
}

我们发现,加入 @Transactional 注解后,在程序抛出异常之后,事务会自动回滚,我们实现了 Spring Boot 中最简单的事务管理。

4 @Transactional 注解部分属性介绍

value/transactionManager

当配置了多个事务管理器时,可以使用 value 属性或者 transactionManager 属性指定选择哪个事务管理器。不管是 JPA 还是 JDBC 等都实现自接口 PlatformTransactionManager。如果添加的是 spring-boot-starter-jdbc 依赖,框架会默认注入 DataSourceTransactionManager 实例。如果添加的是 spring-boot-starter-data-jpa 依赖,框架会默认注入 JpaTransactionManager 实例。

propagation

该属性控制事务的传播行为,其默认值为 Propagation.REQUIRED

可选值如下

  1. PROPAGATION_REQUIRED:表示当前方法必须运行在事务中。如果当前事务存在,方法将会在该事务中运行。否则,会启动一个新的事务
  2. PROPAGATION_SUPPORTS:表示当前方法不需要事务上下文,但是如果存在当前事务的话,那么该方法会在这个事务中运行
  3. PROPAGATION_MANDATORY:表示该方法必须在事务中运行,如果当前事务不存在,则会抛出一个异常
  4. PROPAGATION_REQUIRED_NEW:表示当前方法必须运行在它自己的事务中。一个新的事务将被启动。如果存在当前事务,在该方法执行期间,当前事务会被挂起。如果使用JTATransactionManager的话,则需要访问TransactionManager
  5. PROPAGATION_NOT_SUPPORTED:表示该方法不应该运行在事务中。如果存在当前事务,在该方法运行期间,当前事务将被挂起。如果使用JTATransactionManager的话,则需要访问TransactionManager
  6. PROPAGATION_NEVER:表示当前方法不应该运行在事务上下文中。如果当前正有一个事务在运行,则会抛出异常
  7. PROPAGATION_NESTED:表示如果当前已经存在一个事务,那么该方法将会在嵌套事务中运行。嵌套的事务可以独立于当前事务进行单独地提交或回滚。如果当前事务不存在,那么其行为与PROPAGATION_REQUIRED一样。注意各厂商对这种传播行为的支持是有所差异的。可以参考资源管理器的文档来确认它们是否支持嵌套事务

isolation

即事务的隔离级别,默认值为 Isolation.DEFAULT。

  1. ISOLATION_DEFAULT 使用后端数据库默认的隔离级别
  2. ISOLATION_READ_UNCOMMITTED 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读
  3. ISOLATION_READ_COMMITTED 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生
  4. ISOLATION_REPEATABLE_READ 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生
  5. ISOLATION_SERIALIZABLE 最高的隔离级别,完全服从ACID的隔离级别,确保阻止脏读、不可重复读以及幻读,也是最慢的事务隔离级别,因为它通常是通过完全锁定事务相关的数据库表来实现的

timeout

事务的超时时间,默认值为-1。如果超过该时间限制但事务还没有完成,则自动回滚事务。

扫描二维码关注公众号,回复: 7644034 查看本文章

readOnly

指定事务是否为只读事务,默认值为 false。为了忽略那些不需要事务的方法,比如读取数据,可以设置 read-only 为 true。

rollbackFor

用于指定能够触发事务回滚的异常类型,可以指定多个异常类型。

noRollbackFor

抛出指定的异常类型,不回滚事务,也可以指定多个异常类型。

参考:Spring Boot 中使用 @Transactional 注解配置事务管理

猜你喜欢

转载自blog.csdn.net/Geffin/article/details/100603660