【Spring 持久层】Spring 事务开发、事务属性详解
持久层
- 事务回顾
- Spring 事务编程开发
- Spring 中的事务属性(Transaction Attribute)
- 隔离属性(ISOLATION)
- 传播属性(PROPAGATION)
- 只读属性(readOnly)
- 超时属性(timeout)
- 异常属性
- 事务属性常见配置总结
- 基于标签的事务配置方式
更多内容请查看笔记目录:【Spring 5.x】学习笔记汇总
事务回顾
什么是事务?
- 事务时保证业务操作完整性的一种数据库机制。
事务的 4 大特点: A
、C
、I
、D
A
原子性C
一致性I
隔离性D
持久性
如何控制事务?(JDBC、Mybatis)
JDBC
Connection.setAutoCommit(false);
Connection.commit();
Connection.rollback();
Mybatis
- Mybatis 自动开启事务
sqlSession.commit();
,底层还是调用的Connection
sqlSession.rollback();
,底层还是调用的Connection
结论:控制事务的底层,都是通过 Connection
对象完成的。
Spring 事务编程开发
- 搭建开发环境
pom.xml
<dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>5.2.6.RELEASE</version>
</dependency>
- 编码
<bean id="userService" class="com.yusael.service.UserServiceImpl"><property name="userDAO" ref="userDAO"/>
</bean><!--DataSourceTransactionManager-->
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/>
</bean>@Transactional
public class UserServiceImpl implements UserService {private UserDAO userDAO;<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
- 细节
进行动态代理底层实现的切换,默认false
是 JDK,true
是 Cglib。
<tx:annotation-driven transaction-manager="dataSourceTransactionManager" proxy-target-class="true"/>
Spring 中的事务属性(Transaction Attribute)
什么是事务属性?
属性:描述物体特征的一系列值(性别、身高、体重)
事务属性:描述事务特征的一系列值
- 隔离属性
- 传播属性
- 只读属性
- 超时属性
- 异常属性
如何添加事务属性?
@Transactional(isolation=, propagation=, readOnly=,timeout=,rollbackFor,noRollbackFor=,)
隔离属性(ISOLATION)
概念:描述了事务解决并发问题的特征。
- 什么是并发?
多个事务(用户)在同一时间,访问操作了相同的数据。
同一时间:0.000 几秒左右 - 并发会产生那些问题?
- 脏读
- 不可重复读
- 幻影读
- 并发问题如何解决?
通过隔离属性解决,隔离属性中设置不同过的值,解决并发处理的过程中的问题。
事务并发产生的问题:
- 脏读
一个事务,读取了另一个事务中没有提交的数据,会在本事务中产生数据不一样的现象
解决方案:@Transaction(isolation=Isolation.READ_COMMITTED)
- 不可重复读
一个事务中,多次读取相同的数据,但是读取结果不一样,会在本事务中产生数据不一样的现象
注意:1.不是脏读 2.在一个事务中
解决方案:@Transaction(isolation=Isolation.REPEATABLE_READ)
本质:一把行锁(对数据库表的某一行加锁) - 幻影读
一个事务中,多次对整表进行查询统计,但是结果不一样,会在本事务中产生数据不一致的问题
解决方案:@Transaction(isolation=Isolation.SERIALIZABLE)
本质:表锁(对数据库某个表加锁)
安全与效率对比:
- 并发安全:
SERIALIZABLE
>READ_ONLY
>READ_COMMITTED
- 运行效率:
READ_COMMITTED
>READ_ONLY
>SERIALIZABLE
数据库对隔离属性的支持:
隔离属性的值 | MySQL | Oracle |
---|---|---|
ISOLATION_READ_COMMITTED
|
支持 | 支持 |
ISOLATION_REPEATABLE_READ
|
支持 | 不支持 |
ISOLATION_SERIALIZABLE
|
支持 | 支持 |
- Oracle 不支持
REPEATABLE_READ
,那该如何解决不可重复读?
采用 多版本比对 的方式解决不可重复读问题。
默认的隔离属性:
- Spring 会指定为
ISOLATION_DEFAULT
,调用不同数据库所设置的默认隔离属性
MySQL:REPEATABLE_READ
Oracle:READ_COMMITTED
- 查看数据库的默认隔离属性:
MySQL:SELECT @@tx_isolation;
Oracle:较麻烦,建议百度。
隔离属性在实验中的建议:
- 推荐使用 Spring 默认指定的
ISOLATION_DEFAULT
- 未来的实战中,遇到并发访问的情况,很少见
- 如果真的遇到并发问题,解决方案:乐观锁
Hibernate(JPA):version
MyBatis:通过拦截器自定义开发
传播属性(PROPAGATION)
概念:描述了事务解决 嵌套 问题 的特征。
事务的嵌套:指的是一个大的事务中,包含了若干个小的事务。
事务嵌套产生的问题: 大事务中融入了很多小的事务,他们彼此影响,最终就导致外部大的事务丧失了事务的原子性。
传播属性的值及其用法:
传播属性的值 | 外部不存在事务 | 外部存在事务 | 用法 | 备注 |
---|---|---|---|---|
REQUIRED | 开启新的事务 | 融合到外部事务中 |
@Transactional(propagation = Propagation.REQUIRED)
|
增、删、改方法 |
SUPPORTS | 不开启事务 | 融合到外部事务中 |
@Transactional(propagation = Propagation.SUPPORTS)
|
查询方法 |
REQUIRES_NEW | 开启新的事务 | 挂起外部事务,创建新的事务 |
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
日志记录方法中 |
NOT_SUPPORTED | 不开启事务 | 挂起外部事务 |
@Transactional(propagation = Propagation.NOT_SUPPORTED)
|
极其不常用 |
NEVER | 不开启事务 | 抛出异常 |
@Transactional(propagation = Propagation.NEVER)
|
极其不常用 |
MANDATORY | 抛出异常 | 融合到外部事物中 |
@Transactional(propagation = Propagation.MANDATORY)
|
极其不常用 |
Spring 中传播属性的默认值是:REQUIRED
推荐传播属性的使用方式:
- 增删改 方法:使用默认值 REQUIRED
- 查询 方法:显示指定传播属性的值为 SUPPORTS
只读属性(readOnly)
针对于 只进行查询操作的业务方法,可以加入只读属性,提高运行效率。
默认值:false
@Transactional(readOnly = true)
超时属性(timeout)
指定了事务等待的最长时间。
- 为什么事务会进行等待?
当前事务访问数据时,有可能访问的数据被别的事务进行加锁的处理,那么此时本事务就必须进行等待。 - 等待时间,单位是 秒
- 如何使用:
@Transactional(timeout = 2)
- 超时属性的默认值:-1
-1 表示超时属性由对应的数据库来指定(一般不会主动指定,-1 即可)
异常属性
Spring 事务处理过程中:
- 默认对于
RuntimeException
及其子类,采用 回滚 的策略。 - 默认对于
Exception
及其子类,采用 提交 的策略。
使用方法:
@Transactional(rollbackFor = java.lang.Exception.class, xxx, xxx)@Transactional(noRollbackFor = java.lang.RuntimeException, xxx, xxx)
建议:实战中使用 RuntimeException
及其子类,使用事务异常属性的默认值。
事务属性常见配置总结
- 隔离属性 默认值
- 传播属性 Required(默认值)增删改、Supports 查询操作
- 只读属性 readOnly=false 增删改,true 查询操作
- 超时属性 默认值 -1
- 异常属性 默认值
增删改操作:@Transactional
查询操作:@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
基于标签的事务配置方式
基于注解 @Transaction
的事务配置回顾:
<bean id="userService" class="com.yusael.service.UserServiceImpl"><property name="userDAO" ref="userDAO"/>
</bean><!--DataSourceTransactionManager-->
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/>
</bean>@Transactional
public class UserServiceImpl implements UserService {private UserDAO userDAO;<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
基于标签的事务配置:
<!--DataSourceTransactionManager-->
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/>
</bean><tx:advice id="txAdvice" transaction-manager="dataSourceTransactionManager"><tx:attributes><tx:method name="register" isolation="DEFAULT" propagation="REQUIRED"/></tx:attributes>
</tx:advice><aop:config><aop:pointcut id="pc" expression="execution(* com.yusael.service.UserServiceImpl.register(..))"/><aop:advisor advice-ref="txAdvice" pointcut-ref="pc"/>
</aop:config>
基于标签的事务配置在 实战 中的应用方式:
<tx:advice id="txAdvice" transaction-manager="dataSourceTransactionManager"><tx:attributes><tx:method name="register"/><tx:method name="modify*"/>编程时候, service中负责进行增删改操作的方法 都以 modify 开头查询操作 命名无所谓<tx:method name="*" propagation="SUPPORTS" read-only="true"/></tx:attributes>
</tx:advice><aop:config><aop:pointcut id="pc" expression="execution(* com.yusael.service..*.*(..))"/>应用的过程中, 将 service 都放到 service 包下<aop:advisor advice-ref="txAdvice" pointcut-ref="pc"/>
</aop:config>
【Spring 持久层】Spring 事务开发、事务属性详解相关推荐
- spring MVC请求处理类注解属性详解
spring MVC请求处理类注解属性详解
- 一文带你轻松搞懂事务隔离级别(图文详解)
本文由 SnailClimb 和读者 BugSpeak 共同完成. 事务隔离级别(图文详解) 什么是事务? 事务是逻辑上的一组操作,要么都执行,要么都不执行. 事务最经典也经常被拿出来说例子就是转账了 ...
- 数据库事务隔离级别举例详解
目录 一.前言 1.1.4种事务隔离级别 1.2.3种读现象 二.举例说明 2.1.读未提交 2.2.读已提交 2.3.可重复读 2.4.串行化 一.前言 本文主要对4种事务隔离级别,具体举例说明各自 ...
- spring之旅第四篇-注解配置详解
spring之旅第四篇-注解配置详解 一.引言 最近因为找工作,导致很长时间没有更新,找工作的时候你会明白浪费的时间后面都是要还的,现在的每一点努力,将来也会给你回报的,但行好事,莫问前程!努力总不会 ...
- springboot+jsp中文乱码_【spring 国际化】springMVC、springboot国际化处理详解
在web开发中我们常常会遇到国际化语言处理问题,那么如何来做到国际化呢? 你能get的知识点? 使用springgmvc与thymeleaf进行国际化处理. 使用springgmvc与jsp进行国际化 ...
- MySQL事务及隔离级别详解
MySQL事务及隔离级别详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.MySQL的基本架构 MySQL的基本架构可以分为三块,即连接池,核心功能层,存储引擎层. 1> ...
- 【夯实Spring Cloud】Spring Cloud中使用Hystrix实现断路器原理详解(上)
本文属于[夯实Spring Cloud]系列文章,该系列旨在用通俗易懂的语言,带大家了解和学习Spring Cloud技术,希望能给读者带来一些干货.系列目录如下: [夯实Spring Cloud]D ...
- java 一个大事务下的新增、修改、查询_一文带你轻松搞懂事务隔离级别(图文详解)...
点击上方"linkoffer", 选择关注公众号高薪职位第一时间送达 本文由 SnailClimb 和读者 BugSpeak 共同完成. 事务隔离级别(图文详解) 什么是事务? 事 ...
- 事务隔离级别(图文详解)
事务隔离级别(图文详解) 什么是事务? 事务是逻辑上的一组操作,要么都执行,要么都不执行. 事务最经典也经常被拿出来说例子就是转账了.假如小明要给小红转账1000元,这个转账会涉及到两个关键操作就是: ...
- Spring Cloud:使用Ribbon实现负载均衡详解(下)
在上一篇文章(Spring Cloud:使用Ribbon实现负载均衡详解(上))中,我对 Ribbon 做了一个介绍,Ribbon 可以实现直接通过服务名称对服务进行访问.这一篇文章我详细分析一下如何 ...
最新文章
- 2019年物联网发展的六大趋势
- ipv6前缀长度计算_IPv6和IPv4中对比看RIP
- Linux Oracle10g安装
- 内部类不能有静态变量(除静态的对Static的理解)
- 一文读懂RPA与BPM的区别和联系
- 如何在SAP ABAP development studio里进行代码coverage分析
- 结婚生娃和去核电站参观,哪个更安全?
- mongodb数组更新操作符$push
- 犹如“狼来了”!折叠屏手机Galaxy Fold可能下月上市
- 笔记本我的计算机怎么找不到了,Win10我的电脑在哪?图标没了怎么办?Win10此电脑不见了解决方法...
- Android编译过程详解(三)
- 四分之一波长传输线应用举例
- Python 调用 Everything 进行查找文件
- 人脸检测——RetinaFace
- 戏说CAD开发 最简单角度看CAD软件
- ZOJ 1516 Uncle Tom's Inherited Land
- SpringCache-redis缓存学习记录
- 大数据之Hadoop3.x 运行环境搭建(手把手搭建集群)
- 离网型风力发电机与并网型风力发电机之间的区别
- 阿里-蚂蚁金服社招面经