(九)Spring 事务开发、事务属性详解

持久层

事务回顾

什么是事务?

  • 事务时保证业务操作完整性的一种数据库机制

事务的 4 大特点: ACID

  • 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>@Transactionalpublic 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)

什么是事务属性

属性:描述物体特征的一系列值(性别、身高、体重)

事务属性:描述事务特征的一系列值

  1. 隔离属性
  2. 传播属性
  3. 只读属性
  4. 超时属性
  5. 异常属性

如何添加事务属性?

@Transactional(isolation=, propagation=, readOnly=,timeout=,rollbackFor,noRollbackFor=,)

隔离属性(ISOLATION)

概念:描述了事务解决并发问题的特征

  1. 什么是并发?
    多个事务(用户)在同一时间,访问操作了相同的数据。
    同一时间:0.000 几秒左右
  2. 并发会产生那些问题?
    • 脏读
    • 不可重复读
    • 幻影读
  3. 并发问题如何解决?
    通过隔离属性解决,隔离属性中设置不同过的值,解决并发处理的过程中的问题。

事务并发产生的问题:

  • 脏读
    一个事务,读取了另一个事务中没有提交的数据,会在本事务中产生数据不一样的现象
    解决方案:@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 支持 支持hi
  • 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)

指定了事务等待的最长时间。

  1. 为什么事务会进行等待?
    当前事务访问数据时,有可能访问的数据被别的事务进行加锁的处理,那么此时本事务就必须进行等待。
  2. 等待时间,单位是 
  3. 如何使用:@Transactional(timeout = 2)
  4. 超时属性的默认值:-1
    -1 表示超时属性由对应的数据库来指定(一般不会主动指定,-1 即可)

异常属性

Spring 事务处理过程中:

  • 默认对于 RuntimeException 及其子类,采用 回滚 的策略。
  • 默认对于 Exception 及其子类,采用 提交 的策略。

使用方法:

@Transactional(rollbackFor = java.lang.Exception.class, xxx, xxx)@Transactional(noRollbackFor = java.lang.RuntimeException, xxx, xxx)

建议:实战中使用 RuntimeException 及其子类,使用事务异常属性的默认值。

事务属性常见配置总结

  1. 隔离属性 默认值
  2. 传播属性 Required(默认值)增删改、Supports 查询操作
  3. 只读属性 readOnly=false 增删改,true 查询操作
  4. 超时属性 默认值 -1
  5. 异常属性 默认值

增删改操作:@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>@Transactionalpublic 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>

来源:https://www.icode9.com/content-4-838801.html

(0)

相关推荐

  • Spring事务总结

    Spring事务总结

  • Spring事务入门简介及AOP陷阱分析

    Spring事务入门简介及AOP陷阱分析转载请注明出处: https://www.cnblogs.com/qnlcy/p/15237377.html一.事务的定义事务(Transaction),是指访 ...

  • (十二)Spring从入门到入土——Spring事务

    Spring事务 事务是逻辑上的一组操作,要么都执行,要么都不执行 事务的特性(ACID) 原子性 一致性 隔离性 持久性 Spring管理事务的方式有几种 程序是否支持事务是取决于数据库是否支持事务 ...

  • 中考数学九种题型 五种策略详解,全面攻破压轴题!

    初中数学预习 初中数学预习(ID:zksxyx100)是综合评价中心联合玖桔教育传媒集团,整合全国教育资源打造的教育融媒体平台,为学生.家长.教师提供教育资讯.教育活动和全面的教育服务. 公众号 很多 ...

  • NRF24L01无线串口开发板程序详解

    NRF24L01无线串口开发板程序详解

  • C++17新属性详解

    C++迭代速度相对来说还是比较慢的,2010年以后,C++的新版本迭代速度有所加快,这一点,从C++标准版本的历史发布图1就可以看出来: 图1 C++正式版本发布历史 C++11算是更新比较大的一次了 ...

  • z-index属性详解

    目录 z-index属性详解 一.定义和用法 二.代码 三.效果图 一.定义和用法 z-index属性指定一个元素的堆叠顺序,也就是z轴 position属性定义的是x轴和y轴 z-index属性必须 ...

  • 案例 | 主机厂整车开发流程(CPMP)详解

    IATF16949服务平台 汽车行业专业知识库

  • ​片区开发模式盈利详解

    来源:搜狐网 随着地产开发行业战况愈演愈烈,片区开发开始进入大众视野,片区开发并不是近年来兴起的新鲜词汇,多年来片区开发的模式已经不断升级革新,本文对时下最热的几种模式进行分析. 一 模式概述 1.产 ...

  • 九上物理电学部分知识点详解 精选练习题,期中考前必看!

    每天一起涨知识! 初三的同学们已经进入电学部分了,这部分可以说是整个初中物理学习的重点当然也是难点,所以对于这部分知识,大家不能操之过急,上课一定要认真听讲,跟着老师的节奏走,课前预习和课后复习也是非 ...

  • RayFire Voronoi放射型破碎法相关属性详解

    RayFire的Voronoi放射型破碎法,是一个很典型的点云破碎法,其显著特点是类似蜘蛛网的结构,呈现出由中心点向外延伸的圈状破碎效果. 不同于Voronoi其他类型的破碎法,放射型破碎法拥有其专属 ...

  • java基础开发泛型类的详解

    目录前言泛型概念泛型类结论前言在软件开发中,有许多执行过程很类似,许多人使用复制粘贴完成功能,这种做法虽然编译器不会报错,但会使用波浪线给出提示,给以后的维护带来了很大的隐患.这种情况开发人员通常根据 ...