hooyantsing's Blog

P40 - P49 事务操作

字数统计: 1.3k阅读时长: 5 min
2022/05/31

视频源:尚硅谷Spring框架视频教程(spring5源码级讲解)

事务概念

1. 什么是事务

事务是数据库操作最基本单元,逻辑上一组操作,要么都成功,如果有一个失败所有操作都失败。

2. 事务四个特性(ACID)

  • 原子性:不可分割,要么都成功要么都失败;
  • 一致性:操作前后总量不变;
  • 隔离性:多事务操作时互不影响;
  • 持久性:提交后保存数据。

搭建事务操作环境

image-20220531165138468

事务操作过程

1
2
3
4
5
6
7
8
9
10
11
12
public void accountMoney() {
try {
// 第一步 开启事务
// 第二步 进行业务操作
userDao.reduceMoney();
int i = 10/0;
userDao.addMoney();
// 第三步 没有发生异常,提交事务
} catch(Excepiton e) {
// 第三步 出现异常,回滚事务
}
}

Spring 事务管理介绍

1. 事务添加到 JavaEE 三层结构里面 Service 层(业务逻辑层)

2. 在 Spring 进行事务管理操作

有两种方式:

  • 编程式事务管理;
  • 声明式事务管理(常用)。
    • 基于注解方式;
    • 基于 xml 配置文件方式。

4. 在 Spring 进行声明式事务管理,底层使用 AOP 原理

5. 提供一个接口,代表事务管理器,这个接口针对不同的框架提供不同的实现类

image-20220531171508035

注解声明式事务管理

Step 01 在 spring 配置文件配置事务管理器

1
2
3
4
<!-- 创建事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>

Step 02 在 spring 配置文件,开启事务注解

在 spring 配置文件引入命名空间 tx

1
2
xmlns:util="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"

开启事务注解

1
2
<!-- 开启事务注解 -->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

Step 03 在 service 类(方法)上面添加事务注解 @Transactional

1
2
3
4
5
6
@Transactional
public void accountMoney() {
userDao.reduceMoney();
int i = 10/0;
userDao.addMoney();
}

声明式事务管理参数配置

1. 在 Service 类上面添加注解 @Transactional,在这个注解里面可以配置事务相关参数

image-20220602152127490

  • propagation:事务传播行为;

    多事务方法(对数据库表增删改操作)之间进行调用

    image-20220602154647748

    Spring 框架事务传播行为有 7 种:

    image-20220602155013395

    • REQUIRED(默认):如果 add 方法本身有事务,调用 update 方法后,update 使用当前 add 方法的事务;如果 add 方法本身没有事务,调用 update 方法后,创建新事务;
    • REQUIRED_NEW:使用 add 方法调用 update 方法,如果 add 无论是否有事务,都创建新的事务;
    1
    2
    @Transactional(propagation = Propagation.REQUIRED)
    public class UserService{}
  • Isolation:事务隔离级别;

    遇到的三个问题:

    • 脏读:一个未提交的事务读取到另一个未提交事务的数据;
    • 不可重复读:一个未提交事务读取到另一个提交事务修改之前的数据;
    • 幻读:

    此部分建议专门搜索相关知识点。

    解决问题,设置事务隔离级别:

    image-20220602161042562

    1
    2
    @Transactional(isolation = Isolation.REPEATABLE_READ)
    public class UserService{}
  • timeout:超时时间;

    事务需要在一定时间内进行提交,如果不提交进行回滚。默认值 -1,即无超时时间。单位秒。

  • readOnly:是否只读;

    默认值 false,设置 true 后,只能查询操作。

    1
    2
    @Transactional(timeout = true)
    public class UserService{}
  • rollbackFor:回滚;

    设置出现哪些异常进行事务回滚。

  • noRollbackFor:不回滚;

    设置出现哪些异常不进行事务回滚。

XML 声明式事务管理

1. 在 spring 配置文件中进行配置

Step 01 配置事务管理器

1
2
3
4
<!-- 创建事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>

Step 02 配置通知

1
2
3
4
5
6
7
8
<!-- 配置通知 -->
<tx:advice id="txadvice">
<!-- 配置事务参数 -->
<tx:attributes>
<!-- 指定哪种规则的方法上面添加事务 -->
<tx:method name="accountMoney" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>

Step 03 配置切入点和切面

1
2
3
4
5
6
<aop:config>
<!-- 配置切入点 -->
<aop:pointcut id="pt" expression="execution(* com.atguigu.spring5.service.UserService.*(..))"/>
<!-- 配置切面 -->
<aop:advisor advice-ref="txadvice" pointcut-ref="pt"/>
</aop:config>

完全注解开发

1. 创建配置类,使用配置类代替 xml 配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@Configuration // 配置类
@ComponentScan(basePackages = "com.atguigu") // 组件扫描
@EnableTransactionManagement // 开启事务
public class TxConfig {

// 创建数据库连接池
@Bean
public DruidDataSource getDruidDataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///user_db");
dataSource.setUsername("root");
dataSource.setPassword("root");
return dataSource;
}

// 创建 JdbcTemplate 对象
@Bean
public JdbcTemplate getJdbcTemplate(DataSource dataSource) {
// 到 IOC 容器中根据类型找到 dataSource
JdbcTemplate jdbcTemplate = new JdbcTemplate();
// 注入 dataSource
jdbcTemplate.setDataSource(dataSource);
return jdbcTemplate;
}

// 创建事务管理器对象
@Bean
public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource) {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
return transactionManager;
}
}
CATALOG
  1. 1. 事务概念
    1. 1.1. 1. 什么是事务
    2. 1.2. 2. 事务四个特性(ACID)
  2. 2. 搭建事务操作环境
    1. 2.1. 事务操作过程
  3. 3. Spring 事务管理介绍
    1. 3.1. 1. 事务添加到 JavaEE 三层结构里面 Service 层(业务逻辑层)
    2. 3.2. 2. 在 Spring 进行事务管理操作
    3. 3.3. 4. 在 Spring 进行声明式事务管理,底层使用 AOP 原理
    4. 3.4. 5. 提供一个接口,代表事务管理器,这个接口针对不同的框架提供不同的实现类
  4. 4. 注解声明式事务管理
  5. 5. 声明式事务管理参数配置
    1. 5.1. 1. 在 Service 类上面添加注解 @Transactional,在这个注解里面可以配置事务相关参数
  6. 6. XML 声明式事务管理
    1. 6.1. 1. 在 spring 配置文件中进行配置
  7. 7. 完全注解开发
    1. 7.1. 1. 创建配置类,使用配置类代替 xml 配置文件