我们可以把事务理解为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}。