Spring Boot 复习之事务管理

534 阅读3分钟

我们可以把事务理解为sql语句的批处理,但这个批处理是一个不可分割的原子(atom),要么都执行,要么都回滚(rollback)不执行

我们可以举例说明,在人员管理系统中删除一个员工信息的同时,与之相关的信息也要都删除。转账的时候,一个用户的账户减去多少钱,就要保证被转入的用户的中增加相应数量的钱。这些sql语句必须作为一个整体来执行。

事务的ACID(Atomic、Consistent、Isolated、Durable)

Atomic:原子性

事务的原子性是指事务是一个不可分割的工作单位,这组操作要么全部发生,否则全部不发生。

Consistent:一致性

在事务开始以前,被操作的数据的完整性处于一致性的状态,事务结束后,被操作的数据的完整性也必须处于一致性状态。

Isolated:隔离性

事务隔离性要求系统必须保证事务不受其他并发执行的事务的影响,也即要达到这样一种效果:对于任何一对事务T1 和 T2,在事务 T1 看来,T2 要么在 T1 开始之前已经结束,要么在 T1 完成之后才开始执行。这样,每个事务都感觉不到系统中有其他事务在并发地执行。

Durable:持久性

一个事务一旦成功提交,它对数据库的改变必须是永久的,即便是数据库发生故障也应该不回对其产生任何影响。

在Spring Boot中,使用事务管理的简单方法,使用@Transactiona注解

当我们使用了spring-boot-starter-jdbc或spring-boot-starter-data-jpa依赖的时候,框 架会自动默认分别注入DataSourceTransactionManager或者JpaTransactionManager。所以我们不需要任何额外配置就可以用@Transactional注解进行事务的使用。

第一步配置依赖,这里默认为mysql数据库


<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
	</dependency>
<dependency>     
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
<dependency>
                         <groupId>org.mybatis.spring.boot</groupId>
                         <artifactId>mybatis-spring-boot-starter</artifactId>
                         <version>2.0.1</version>
</dependency>
	<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
	</dependency>

然后application.properties配置

server.port=8080
spring.profiles.active=debug
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/oaoth?useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=true&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=191513
mybatis.type-aliases-package=com.redrock.oauth
mybatis.configuration.mapUnderscoreToCamelCase=true

使用@EnableTransactionManagement 和 @Transactional

在启动类支持事务管理

@MapperScan("com.redrock.oauth.mapper")
@SpringBootApplication
@EnableTransactionManagement
public class OauthApplication {

    public static void main(String[] args) {
        SpringApplication.run(OauthApplication.class, args);
    }

}

在服务层加上@Transactional注解

@Transactional(rollbackFor = {Exception.class})
public void deleteUser(String username) {
    int user_id = userMapper.getPassword(username).getUser_id();
    //判断该用户是否已经存在
    if (userMapper.IfUserExist(user_id) == 0) {
        throw new DefinedException(ResultEnum.PARAM_ERROR, "该用户不存在");
    }
    if(userMapper.getStatus(user_id)==2){
        throw new DefinedException(ResultEnum.DELETED,"用户已被删除");
    }
    userMapper.deleteUser(username);
}

error是一定会回滚的,这里Exception是异常,他又分为运行时异常RuntimeException和非运行时异常。

借图

回滚类型如下:

让checked例外也回滚:

在整个方法前加上 @Transactional(rollbackFor=Exception.class) 

让unchecked例外不回滚: 

@Transactional(notRollbackFor=RunTimeException.class) 

不需要事务管理的(只查询的)方法:@Transactional(propagation=Propagation.NOT_SUPPORTED)

注意: 如果异常被try{}catch{}了,事务就不回滚了,如果想让事务回滚必须再往外抛try{}catch{throw Exception}。