首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【Java EE进阶 --- SpringBoot】Spring事务

【Java EE进阶 --- SpringBoot】Spring事务

作者头像
optimistic_chen
发布2026-01-14 20:45:42
发布2026-01-14 20:45:42
1640
举报

前言

事务是⼀组操作的集合,是⼀个不可分割的操作.

事务这个词,在数据库学习后都会有了解,如它的概念:事务会把所有的操作作为一个整体,向数据库发起请求,要么都成功,要么一起失败。

事务的基本操作: 1. 开启事务 :start transaction/begin(一组操作前开启事务) 2. 提交事务:commit (操作全部成功,提交事务) 3. 回滚事务:rollback(一组操作中任何一个操作出现问题,整组回滚)

Spring 中的事务

Spring 中的事务分为两类:

  • 编程式事务(手动写代码操作事务)
  • 声明式事务(利用注解自动开启和提交事务)

准备工作

数据库:

代码语言:javascript
复制
-- 创建数据库
DROP DATABASE IF EXISTS trans_test;
CREATE DATABASE trans_test DEFAULT CHARACTER SET utf8mb4;

-- ⽤⼾表
DROP TABLE IF EXISTS user_info;
CREATE TABLE user_info (
   `id` INT NOT NULL AUTO_INCREMENT,
   `user_name` VARCHAR (128) NOT NULL,
   `password` VARCHAR (128) NOT NULL,
   `create_time` DATETIME DEFAULT now(),
   `update_time` DATETIME DEFAULT now() ON UPDATE now(),
   PRIMARY KEY (`id`)
 ) ENGINE = INNODB DEFAULT CHARACTER 
SET = utf8mb4 COMMENT = '⽤⼾表';

--操作日志表
DROP TABLE IF EXISTS log_info;
CREATE TABLE log_info (
  `id` INT PRIMARY KEY auto_increment,
  `user_name` VARCHAR ( 128 ) NOT NULL,
  `op` VARCHAR ( 256 ) NOT NULL,
  `create_time` DATETIME DEFAULT now(),
  `update_time` DATETIME DEFAULT now() ON UPDATE now() 
) DEFAULT charset 'utf8mb4';

同时引入Spring Web, Mybatis , mysql 等多种依赖 设置配置文件

代码语言:javascript
复制
spring:
 datasource:
   url: jdbc:mysql://127.0.0.1:3306/trans_testcharacterEncoding=utf8&useSSL=false
   username: root
   password: root
   driver-class-name: com.mysql.cj.jdbc.Driver
 mybatis:
   configuration: # 配置打印MyBatis⽇志
     log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
     map-underscore-to-camel-case: true #配置驼峰⾃动转换

实体类:

代码语言:javascript
复制
import java.util.Date;
@Data
public class UserInfo {
    private Integer id;
    private String userName;
    private String password;
    private Date createTime;
    private Date updateTime;
}
代码语言:javascript
复制
@Data
public class LogInfo {
    private Integer id;
    private String userName;
    private String op;
    private Date createTime;
    private Date updateTime;
}

Controller:

代码语言:javascript
复制
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    @RequestMapping("/registry")
    public String registry(String name,String password){
        //用户注册(数据操作)
        userService.registryUser(name,password);
        log.info("用户注册成功");
        return "注册成功";
    }
}

Service:

代码语言:javascript
复制
@Service
@Slf4j
public class UserService {
    @Autowired
    private UserInfoMapper userInfoMapper;

    public Integer registryUser(String name,String password){
         return userInfoMapper.insert(name,password);
    }
}
代码语言:javascript
复制
@Service
@Slf4j
public class LogService {
    @Autowired
    private LogInfoMapper logInfoMapper;
    public Integer insertLog(String name,String password){
       return  logInfoMapper.insertLog(name,"用户注册");
    }
}

Mapper:

代码语言:javascript
复制
@Mapper
public interface UserInfoMapper {
    @Insert("insert into user_info(`user_name`,`password`) value(#{name},#{password})")
    Integer insert(String name,String password);
}
代码语言:javascript
复制
@Mapper
public interface LogInfoMapper {
    @Insert("insert into log_info(`user_name`,`op`)values(#{name},#{op})")
    Integer insertLog(String name,String op);
}

Spring编程式事务

Spring手动操作事务与MySQL类似,三个关键步骤:开启事务、提交事务、回滚事务。

Spring Boot内置的两个对象:

  • DataSourceTransactionManager 事务管理器:用来获取事务(开启事务),提交或者回滚事务。
  • TransactionDefinition 是事务的属性,获取事务时将属性传进去从而获得一个事务的TransactionStatus
代码语言:javascript
复制
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    @Autowired
    private DataSourceTransactionManager dataSourceTransactionManager;//事务管理器

    @Autowired
    private TransactionDefinition definition;//事务之前状态

    @RequestMapping("/registry")
    public String registry(String name,String password){
        /**
         * 1. 开启事务
         * 2. 数据操作
         * 3. 事务提交、回滚
         */
        //开启事务
        TransactionStatus transaction= dataSourceTransactionManager.getTransaction(definition);
        //用户注册(数据操作)
        userService.registryUser(name,password);
        log.info("用户注册成功");
        //事务提交
        //dataSourceTransactionManager.commit(transaction);
        //事务回滚
        dataSourceTransactionManager.rollback(transaction);
        return "注册成功";
    }
}

postman测试:提交事务

在这里插入图片描述
在这里插入图片描述

Spring声明式事务(@Transactional)

在需要事务的方法上添加@Transactional注解就可以实现,无需手动开启事务,方法执行完会自动提交事务,中途有异常自动回滚事务。

代码语言:javascript
复制
@Slf4j
@RequestMapping("/user2")
@RestController
public class UserController2 {
    @Autowired
    private UserService userService;

    @Autowired
    private LogService logService;

    @Transactional
    @RequestMapping("/registry")
    public String registry(String name,String password){
        userService.registryUser(name,password);
        return "注册成功";
    }
}

运行此程序,发现数据插入成功,但是我们给代码添加异常,会发生什么呢?

代码语言:javascript
复制
@Slf4j
@RequestMapping("/user2")
@RestController
public class UserController2 {
    @Autowired
    private UserService userService;

    @Autowired
    private LogService logService;

    @Transactional
    @RequestMapping("/registry")
    public String registry(String name,String password){
        userService.registryUser(name,password);
        int a=10/0;
        return "注册成功";
    }
}
在这里插入图片描述
在这里插入图片描述

虽然用户注册成功,但是去观察数据库发现没有新增数据,说明事务进行了回滚。

@Transcational

作用

@Transcational可以修饰方法或类:

  • 修饰方法:只有修饰public方法时才生效
  • 修饰类:对 @Transcational 修饰的类中所有public 方法生效

类\方法被@Transcational修饰后,在目标方法执行前就自动开启事务,方法执行完毕自动提交事务。注意:如果方法执行中有异常且未捕获,就进行事务回滚;否则继续提交事务。

针对异常被捕获还需要对事务进行回滚,有两种方法解决:

  1. 重新抛出异常
代码语言:javascript
复制
try {
    //强制程序抛出异
    int a = 10/0;
 }catch (Exception e){
    //将异常重新抛出去
    throw e;
}
  1. 手动回滚
代码语言:javascript
复制
try {
    //强制程序抛出异
    int a = 10/0;
 }catch (Exception e){
    //手动回滚事务
    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    
}

属性

@Transcational注解中常见有三个属性:rollbackFor、Isolation、propagation

rollbackFor

rollbackFor:异常回滚属性。指定能够触发事务回滚类型的异常类型

@Transactional 默认只在遇到运⾏时异常和Error时才会回滚,⾮运⾏时异常不回滚. 如果需要所有异常都回滚,那配置@Transcational属性中rollbackFor,指定什么异常类型时进行回滚

代码语言:javascript
复制
@Transactional(rollbackFor = Exception.class)

注意: 默认情况下,只有运行时异常RuntimeExpection和Error时才回滚。但是其他类型异常可以通过rollbackFor属性进行指定。

Isolation

Isolation:事务隔离级别,默认是Isolation.DEFAULT

其实MySQL种有4种事务隔离级别:

  1. 读未提交(READ_UNCOMMITTED):也叫未提交读.该隔离级别的事务可以看到其他事务中未提交的数据.
  2. 读提交(READ_COMMITTED):也叫提交读,该隔离级别的事务能读到已提交事务的数据
  3. 可重复读(REPEATABLE_READ):事务不会读到其他事务对已有数据的修改,即使其他事务已提交。保证同一事务多次查询结果一致(MySQL默认事务隔离级别)
  4. 串行化(SERIALIZABLE):序列化,事务最⾼隔离级别.它会强制事务排序,使之不会发⽣冲突。

而Spring中事务隔离级别有5种:

  • Isolation.DEFAULT:以连接的数据库的事务隔离级别为主
  • Isolation.READ_UNCOMMITTED:读未提交
  • Isolation.READ_COMMITTED:读已提交
  • Isolation.REPEATABLE_READ:可重复读
  • Isolation.SERIALIZABLE:串行化

脏读:因为其他事务未提交的数据可能会发⽣回滚,但是该隔离级别却可以读到,我们把该级别读到的数据称之为脏数据。

不可重复读:由于在事务的执⾏中可以读取到其他事务提交的结果,所以在不同时间的相同SQL查询可能会得到不同的结果

幻读:可重复读级别的事务正在执行,另一个事务成功插入某条数据,但是因为它每次查询的结果都是⼀样的,所以会导致查询不到这条数据,⾃⼰重复插⼊时⼜失败(因为唯⼀约束的原因). 明明在事务中查询不到这条信息,但⾃⼰就是插⼊不进去

事务隔离级别

脏读

不可重复读

幻读

读未提交

读已提交

×

可重复读

×

×

串行化

×

×

×

完结撒花!🎉

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2026-01-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • Spring 中的事务
    • 准备工作
    • Spring编程式事务
    • Spring声明式事务(@Transactional)
  • @Transcational
    • 作用
    • 属性
      • rollbackFor
      • Isolation
  • 完结撒花!🎉
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档