尚硅谷课堂笔记:
链接: https://pan.baidu.com/s/1BPdI_vDWW2M-1A0okF3Pww 提取码: 2333
视频的代码笔记和资料。
老师笔记中的某些内容不再赘叙
此笔记 针对以上笔记为基础 添加补充
主要目的为针对自己复习学习
Spring事务
atomicity consistency isolation durability
- 原子性
不可分割 要么都成功 要么都失败
- 一致性
事务提交前后的数据完整性和状态保持一致
总量守恒
- 隔离性
多事务操作之间不影响
不考虑隔离性 产生的问题:脏读 幻读 不可重复读
- 持久性
提交之后 表中的数据真正发生变化
脏读 幻读 不可重复读 的理解
脏读:一个未提交事务读取到另一个未提交事务的数据。
假设事务 A 更新了一行数据的值为 A 值,此时事务 B 去查询了一下这行数据的值,看到的值是 A 值
事务 B 拿着刚才查询到的 A 值做各种业务处理。但是,事务 A 突然回滚了事务,导致它刚才功能的 A 值没了,此时那行数据的值回滚为 NULL 值。然后事务 B 紧接着此时再次查询那行数据的值,看到的居然是 NULL 值
说明隔离级别“READ-UNCOMMITTED” 但这个隔离级别太低了,一般数据库不会采用
不可重复读: 一个未提交事务读取到另一个提交事务修改数据。
前提:必须要事务 B 提交之后,它修改的值才能被事务 A 读取到,其实这种情况下,就是我们首先避免了脏读的发生
假设缓存页里一条数据原来的值是 A 值,此时事务 A 开启之后,第一次查询这条数据,读取到的就是 A 值
接着事务 B 更新了那行数据的值为 B 值,同时事务 B 立马提交了,然后事务 A 此时还没提交。所以事务 A 是可以读到B
紧接着事务 C 再次更新数据为 C 值,并且提交事务了,此时事务 A 在还没提交的情况下,第三次查询数据,查到的值为 C 值
幻读: 一个未提交事务读取到另一个提交事务添加数据。
幻读就是你一个事务用一样的 SQL 多次查询,结果每次查询都会发现查到一些之前没看到过的数据
如
SELECT * FROM table WHERE id > 10
它一开始查询出来了 n 条数据。接着这个时候,别的事务 B往表里插了几条数据,而且事务 B 还提交了,此时多了几行数据。事务 A 此时第二次查询,这次它查询出来了 n+m条数据
幻读,不可重复读 都是现象, 脏读是问题
Spring中 解决通过设置事务隔离级别,解决3个问题。在下面((ioslation:事务隔离级别))
1.注解使用流程
Spring支持声明式事务管理,一般使用注解
在Spring进行声明式事务管理,底层使用AOP原理
platfromTransactionManager
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 组件扫描 -->
<context:component-scan base-package="com.atguigu"></context:component-scan>
<!-- 数据库连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close">
<property name="url" value="jdbc:mysql:///user_DB?useUnicode=true&characterEncoding=utf8" />
<property name="username" value="root" />
<property name="password" value="123456" />
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
</bean>
<!-- JdbcTemplate对象 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--注入dataSource-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--创建事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入数据源,对那个数据库进行事务管理-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--开启事务注解 就是认识事务的注解-->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
</beans>
1、在spring配置文件配置事务管理器
2、在spring配置文件,开启事务注解
3、在service类上面(或者service类里面方法上面)添加事务注解
1)@Transactional,这个注解添加到类上面,也可以添加方法上面
2)如果把这个注解添加类上面,这个类里面所有的方法都添加事务
3)如果把这个注解添加方法上面,为这个方法添加事务
@Service
@Transactional
public class UserService {
2.@Transactional 的属性
tip: idea 中ctrl + p 查看属性
-
1、propagation: 事务传播行为
@Transactional(propagation = Propagation.REQUIRED)
举例
首先这个传播行为是针对于被调用的方法而言的,也就是update方法上设置传播行为
注意:目前的前提都是update有事务
-
2、ioslation:事务隔离级别
@Transactional(isolation = Isolation.REPEATABLE_READ) //MySQL默认就是这个
-
3、timeout: 超时时间
@Transactional(timeout = 5) //@Transactional(timeout = -1)
-
4、readOnly: 是否只读
-
5、rollbackFor: 回滚
设置出现哪些异常进行事务回滚。
-
6、noRollbackFor: 不回滚
设置出现哪些异常不进行事务回滚。
3.纯注解开发
// @Configuration //配置类
//组件扫描 @ComponentScan(basePackages = "com.atguigu")
// @EnableTransactionManagement 开启事务
public class TxConfig {
//创建数据库连接池
//@Component:表示这是一个组件。IOC会托管这个类的对象。@bean:方法返回的对象交给IOC管理。
//@bean:表示方法返回的是对象,然后对象交给IOC管理。在配置文件中配置对象要写上注解@Bean
@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 (好比@@Autowired 根据类型做注入)
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;
}
}
springboot 又进行了进一步封装