
🚀 欢迎来到我的CSDN博客:Optimistic _ chen
✨ 一名热爱技术与分享的全栈开发者,在这里记录成长,专注分享编程技术与实战经验,助力你的技术成长之路,与你共同进步!
🚀我的专栏推荐:
| 专栏 | 内容特色 | 适合人群 |
|---|---|---|
| 🔥C语言从入门到精通 | 系统讲解基础语法、指针、内存管理、项目实战 | 零基础新手、考研党、复习 |
| 🔥Java基础语法 | 系统解释了基础语法、类与对象、继承 | Java初学者 |
| 🔥Java核心技术 | 面向对象、集合框架、多线程、网络编程、新特性解析 | 有一定语法基础的开发者 |
| 🔥Java EE 进阶实战 | Servlet、JSP、SpringBoot、MyBatis、项目案例拆解 | 想快速入门Java Web开发的同学 |
| 🔥Java数据结构与算法 | 图解数据结构、LeetCode刷题解析、大厂面试算法题 | 面试备战、算法爱好者、计算机专业学生 |
🚀我的承诺:
✅ 文章配套代码:每篇技术文章都提供完整的可运行代码示例
✅ 持续更新:专栏内容定期更新,紧跟技术趋势
✅ 答疑交流:欢迎在文章评论区留言讨论,我会及时回复(支持互粉)
🚀 关注我,解锁更多技术干货!
⏳ 每天进步一点点,未来惊艳所有人!✍️ 持续更新中,记得⭐收藏关注⭐不迷路 ✨
📌 标签:#技术博客 #编程学习 #Java #C语言 #算法 #程序员
文章目录
- 前言
- [Spring 中的事务](#Spring 中的事务)
- @Transcational
- 完结撒花!🎉
前言
事务是⼀组操作的集合,是⼀个不可分割的操作.
事务这个词,在数据库学习后都会有了解,如它的概念:事务会把所有的操作作为一个整体,向数据库发起请求,要么都成功,要么一起失败。
事务的基本操作:
- 开启事务 :start transaction/begin(一组操作前开启事务)
- 提交事务:commit (操作全部成功,提交事务)
- 回滚事务:rollback(一组操作中任何一个操作出现问题,整组回滚)
Spring 中的事务
Spring 中的事务分为两类:
- 编程式事务(手动写代码操作事务)
- 声明式事务(利用注解自动开启和提交事务)
准备工作
数据库:
sql
-- 创建数据库
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 等多种依赖
设置配置文件
java
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 #配置驼峰⾃动转换
实体类:
java
import java.util.Date;
@Data
public class UserInfo {
private Integer id;
private String userName;
private String password;
private Date createTime;
private Date updateTime;
}
java
@Data
public class LogInfo {
private Integer id;
private String userName;
private String op;
private Date createTime;
private Date updateTime;
}
Controller:
java
@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:
java
@Service
@Slf4j
public class UserService {
@Autowired
private UserInfoMapper userInfoMapper;
public Integer registryUser(String name,String password){
return userInfoMapper.insert(name,password);
}
}
java
@Service
@Slf4j
public class LogService {
@Autowired
private LogInfoMapper logInfoMapper;
public Integer insertLog(String name,String password){
return logInfoMapper.insertLog(name,"用户注册");
}
}
Mapper:
java
@Mapper
public interface UserInfoMapper {
@Insert("insert into user_info(`user_name`,`password`) value(#{name},#{password})")
Integer insert(String name,String password);
}
java
@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
java
@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注解就可以实现,无需手动开启事务,方法执行完会自动提交事务,中途有异常自动回滚事务。
java
@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 "注册成功";
}
}
运行此程序,发现数据插入成功,但是我们给代码添加异常,会发生什么呢?
java
@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修饰后,在目标方法执行前就自动开启事务,方法执行完毕自动提交事务。 注意:如果方法执行中有异常且未捕获,就进行事务回滚;否则继续提交事务。
针对异常被捕获还需要对事务进行回滚,有两种方法解决:
- 重新抛出异常
java
try {
//强制程序抛出异
int a = 10/0;
}catch (Exception e){
//将异常重新抛出去
throw e;
}
- 手动回滚
java
try {
//强制程序抛出异
int a = 10/0;
}catch (Exception e){
//手动回滚事务
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
属性
@Transcational注解中常见有三个属性:rollbackFor、Isolation、propagation
rollbackFor
rollbackFor:异常回滚属性。指定能够触发事务回滚类型的异常类型
@Transactional 默认只在遇到运⾏时 异常和Error时才会回滚,⾮运⾏时异常不回滚.
如果需要所有异常都回滚,那配置@Transcational属性中rollbackFor,指定什么异常类型时进行回滚
java
@Transactional(rollbackFor = Exception.class)
注意:
默认情况下,只有运行时异常RuntimeExpection和Error时才回滚。但是其他类型异常可以通过rollbackFor属性进行指定。
Isolation
Isolation:事务隔离级别,默认是Isolation.DEFAULT
其实MySQL种有4种事务隔离级别:
- 读未提交(READ_UNCOMMITTED):也叫未提交读.该隔离级别的事务可以看到其他事务中未提交的数据.
- 读提交(READ_COMMITTED):也叫提交读,该隔离级别的事务能读到已提交事务的数据
- 可重复读(REPEATABLE_READ):事务不会读到其他事务对已有数据的修改,即使其他事务已提交。保证同一事务多次查询结果一致(MySQL默认事务隔离级别)
- 串行化(SERIALIZABLE):序列化,事务最⾼隔离级别.它会强制事务排序,使之不会发⽣冲突。
而Spring中事务隔离级别有5种:
- Isolation.DEFAULT:以连接的数据库的事务隔离级别为主
- Isolation.READ_UNCOMMITTED:读未提交
- Isolation.READ_COMMITTED:读已提交
- Isolation.REPEATABLE_READ:可重复读
- Isolation.SERIALIZABLE:串行化
脏读:因为其他事务未提交的数据可能会发⽣回滚,但是该隔离级别却可以读到,我们把该级别读到的数据称之为脏数据。
不可重复读:由于在事务的执⾏中可以读取到其他事务提交的结果,所以在不同时间的相同SQL查询可能会得到不同的结果
幻读:可重复读级别的事务正在执行,另一个事务成功插入某条数据,但是因为它每次查询的结果都是⼀样的,所以会导致查询不到这条数据,⾃⼰重复插⼊时⼜失败(因为唯⼀约束的原因). 明明在事务中查询不到这条信息,但⾃⼰就是插⼊不进去
| 事务隔离级别 | 脏读 | 不可重复读 | 幻读 |
|---|---|---|---|
| 读未提交 | √ | √ | √ |
| 读已提交 | × | √ | √ |
| 可重复读 | × | × | √ |
| 串行化 | × | × | × |
完结撒花!🎉

如果这篇博客对你有帮助,不妨点个赞支持一下吧!👍
你的鼓励是我创作的最大动力~
✨ 想获取更多干货? 欢迎关注我的专栏 → optimistic_chen
📌 收藏本文,下次需要时不迷路!
我们下期再见!💫 持续更新中......
悄悄说:点击主页有更多精彩内容哦~ 😊