回顾事务
事物的四大特征(ACID)
- 原子性
- 一致性
- 隔离性
- 持久性
事务的三种行为
- 开启事务 connection.setAutoCommit(); jdbc默认为false
- 提交事务 connection.commit();
- 回滚事务: connection rollback();
spring中支持的事务管理
一..编程式事务管理
-
获取数据库连接Connection对象
-
取消事务的自动提交【开启事务】
-
执行操作【核心业务代码】
-
正常完成操作时手动提交事务
-
执行失败时回滚事务
-
关闭相关资源
-
发现问题:
-
核心业务代码与事务管理代码【非核心业务】相耦合,导致代码分散及代码混乱问题
-
-
解决思路
-
使用AOP思想【框架】,将事务管理代码先横向提取,再动态织入。【声明式事务管理】
-
二..声明式事务管理 一句话理解
使用aop框架或者aop思想,将事务管理代码先横向提取,再动态织入
1.带入jar包{aspecJ}
<!--spirng声明式事务管理-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.3.1</version>
</dependency>
2.编写配置文件 applicagion 主要配置注解扫描和 数据库链接信息和事务管理配置注解驱动
<?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:aop="http://www.springframework.org/schema/aop"
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.cong"/>
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="username" value="${jdbc.username}"/>
<property name="url" value="${jdbc.url}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置声明式 事务管理-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 引入tx标签 配置事物的注解驱动 如果声明式事务的id是transactionManager 可以不用写因为源码默认就是transactionManager
源码: <xsd:attribute name="transaction-manager" type="xsd:string" default="transactionManager">
-->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
在需要事务的类或者方法上加上注解
@Transactional
propagation【事务传播行为】
![]()
解释常用的
第一个REQUIRED 代表 方法2调用方法1时 用方法1的事务 如果方法1没有事务就自己创建一个事务
第二个 REQUIRES_NEW
代表当前的方法必须启动新的事务 如果调用别的方法时会把调用的方法的事务挂起
其他事务传播行为
传播属性 描述 REQUIRED 如果有事务在运行,当前的方法就在这个事务内运行;否则就启动一个新的事务,并在自己的新事务内运行。 REQUIRES_NEW 当前的方法*必须*启动新事务,并在自己的事务内运行;如果之前有事务正在运行,应该将它挂起。 SUPPORTS 如果有事务在运行,当前的方法就在这个事务内运行,否则可以不运行在事务中。 NOT_SUPPORTED 当前的方法不应该运行在事务中,如果有运行的事务将它挂起 MANDATORY 当前的方法必须运行在事务中,如果没有正在运行的事务就抛出异常。 NEVER 当前的方法不应该运行在事务中,如果有正在运行的事务就抛出异常。 NESTED 如果有事务正在运行,当前的方法就应该在这个事务的嵌套事务内运行,否则就启动一个新的事务,并在它自己的事务内运行。
案例
/*去结账:结账时,账号余额支持买多少本书,就允许用户购买 如账户余额不充足怎么办? 需求1:不允许用户购买所有图书 */ @Transactional(propagation = Propagation.REQUIRED) public void purchase(String username, String isbn) { //查询book价格 Integer price = bookShopDao.findBookPriceByIsbn(isbn); //修改库存 bookShopDao.updateBookStock(isbn); //修改余额 bookShopDao.updateUserAccount(username, price); } /* 去结账:结账时,账号余额支持买多少本书,就允许用户购买 如账户余额不充足怎么办? 需求2:不允许用户购买最后一本(导致余额不足)的图书及其之后的所有图书, 之前的其他图书正常购买 */ @Transactional(propagation = Propagation.REQUIRES_NEW) public void purchase(String username, String isbn) { //查询book价格 Integer price = bookShopDao.findBookPriceByIsbn(isbn); //修改库存 bookShopDao.updateBookStock(isbn); //修改余额 bookShopDao.updateUserAccount(username, price); }
事物的隔离级别
isolation【事务隔离级别】
概述:事务隔离级别就是事务与事务之间隔离等级
隔离级别如下
READ UNCOMMITTED【读未提交】:1
READ COMMITTED【读已提交】:2
REPEATABLE READ【可重复读】:4
SERIALIZABLE【串行化】:8
Oracle与Mysql隔离级别对比
Oracle MySQL READ UNCOMMITTED × √ READ COMMITTED √(默认) √ REPEATABLE READ × √(默认) SERIALIZABLE √ √ 不同隔离级别可能出现现象
timeout【事务超时】
设置事务超时的强制回滚时间
类型:int,单位:秒
默认值:-1
readonly【事务只读】
默认值:false
设置当前事务是否只读
一般查询数据时,设置事务只读,提高一点性能
如增删改操作中设置只读,会报如下错误
Connection is read-only. Queries leading to data modification are not allowed
rollbackFor|noRollbackFor【事务(是否)异常回滚】
rollbackFor:设置回滚的指定异常Class
noRollbackFor:设置不回滚的指定异常Class