Spring事务( Transaction )

事务的概念

事务是一些sql语句的集合,作为一个整体执行,一起成功或者一起失败。

使用事务的时机

一个操作需要多天sql语句一起完成才能成功

程序中事务在哪里说明

加在业务类的方法上面(public方法上面),表示业务方法执行时,需要事务的支持。

不同的事务管理器

不同的数据库访问技术,处理事务是不同的

  1. 使用jdbc 访问数据库,事务处理

    public void updateAccount(){
    Connection con = .....;
    con.setAutoCommit(false);
    state.insert();
    state.update();
    state.commit();
    con.setAutoCommit(true);
    }
  2. MyBatis执行数据库,处理事务

    public void updateAccount(){
    SqlSession sqlSession = SqlSessionFactory.openSession(false);
    try{
    sqlSession.insert(...);
    sqlSession.update(...);
    sqlSession.commit();
    }catch(Exception e){
    sqlSession.rollback();
    }
    }

spring统一管理事务,把不同的数据库访问技术的事务处理统一起来

使用spring的事务管理器,管理不同数据库访问技术的事务处理。开发人员只需要掌握spring的事务处理一个方案,就可以实现使用不同数据库访问技术的事务管理。

尽管事务面向的是spring,有spring管理事务,做事务提交和回滚。

spring事务管理器

spring框架使用事务管理器对象,管理所有的事务。

事务管理器接口: PlatFormTransactionManager

​ 作用 :定义了事务的操作,主要是commit() , rollback()

事务管理器有很多的实现类:一种数据库访问计数有一个实现类。由实现类具体完成事务的提交,回滚。

这意味着:JDBC或者MyBatis访问数据库有自己的事务管理实现类:DataSourceTransactionManager

​ hibernate框架,他的事务管理器实现类:HibernateTransactionManager

事务管理器的工作方式

spring集中统一管理事务,分配管理事务给具体的事务管理器对象。

事务提交和回滚的时机

当业务正常执行的时候,没有异常,事务是提交的。如果业务代码中出现了运行时异常,事务会发生回滚。

异常的分类:

  • Error : 错误,回滚事务
  • Exception:
    • 运行时异常:RuntimeException和他的子类都是运行时异常,在程序执行过程中抛出的异常
    • 受查异常:在编写代码时需要处理的异常(编译都无法通过),会提交事务。

方法抛出运行时异常事务回滚,其他的情况都是执行事务。

spring事务管理的实现方式:AOP中的环绕通知

环绕通知:在目标方法的前后都可以增加功能,不需要修改代码。

// spring给业务方法在执行时,增加事务的切面功能(一下为大致的实现步骤,不是真正的执行代码)
@Around("execution(* com.wang.*.*(..))")
public Object myAround(ProceedingJoinPoint pjp){
try{
PlatformTransactionManager.beginTransaction(); // 使用spring的事务管理器,开启事务
pjp.proceed(); // 执行目标方法
PlatformTransactionManager.commit(); // 业务方法正常执行,事务提交
}catch(Exception e){
PlatformTransactionManager.roolback(); // 业务方法非正常执行,事务回滚
}
}

事务定义接口(TransactionDefinition )

事务定义接口TransactionDefinition中定义了事务描述相关的三类常量:事务隔离级别事务传播行为事务默认超时时限,及他们的操作。

给业务方法说明事务的属性。

隔离级别

定义

控制事务之间的影响速度

具体值
  • DEFAULT:采用DB默认的事务隔离级别。Mysql的默认为REPEATABLE_READOracle默认为READ_COMMITTED
  • READ_UNCOMMITTED:读未提交。未解决任何并发问题
  • READ_COMMITTER:读已提交。解决脏读,存在不可重复读和幻读
  • REPETABLE_READ:可重复读。解决脏读,不可重复读,存在幻读
  • SERIALIZABLE:串行化。不存在并发问题。

事务超时时间

以秒为单位,整数值,默认为-1

超时时间:表示一个业务方法最长的执行时间,到达时间没有执行完毕,spring会回滚事务。

传播行为

传播行为有7个值

定义:业务方法在调用的时候,事务在方法之间的传递和使用。

使用传播行为,表示方法有无事务。

  • PROPAGATION_REQUIRED

  • PROPAGATION_REQUIRES_NEW

  • PROPAGATION_SUPPORTS

    以上三个需要掌握

  • PROPAGATION_MANDATORY

  • PROPAGATION_NESTED

  • PROPAGATION_NEVER

  • PROPAGATION_NOT_SUPPORTED

  1. PROPAGATION_REQUIRED:spring默认传播行为,方法在调用的时候,如果存在事务就是用当前的事务,如果没有事务,就新建一个事务,方法在新事务中执行。
  2. PROPAGATION_SUPPORTS: 方法有事务可以正常执行,没有事务也可以正常执行。(查询操作)
  3. PROPAGATION_REQUIRES_NEW:方法需要一个新事务。如果调用方法的时候,存在一个事务,则原来的事务暂停,知道新事务执行完毕。如果方法调用的时候,没有事务,则新建一个事务,在新事务中执行代码。

spring框架使用自己的注解@Transactional控制事务

@Transactional注解,使用注解的属性控制事务(隔离级别,传播行为,超时)

​ 其中的属性:

  • propagation:事务的传播行为,他使用的Propagation类的枚举值,例如:Propagation.REQUIRED;
  • isolation:表示隔离级别,使用Isolation类的枚举值,表示隔离级别,默认是:Ioslation.DEFAULT;
  • readOnly:boolean类型的值,表示数据库操作是不是只读的,默认为false
  • timeout:事务超时,默认是-1,整数值,单位是秒,例如:timeout=20;
  • rollbackFor:表示回滚的异常类列表,他的值是一个数组,每个值是异常类型的class。
  • rollbackForClassName:表示回滚的异常类列表,是String类型的值
  • noRollbackFor:不需要回滚的异常类列表,是class类型的
  • noRollbackForClassName:不需要回滚的异常类列表,是String类型的值

该注解放置的位置:

  1. 在业务方法上面,实在public方法上面(大多数)
  2. 在类的上面(几乎见不到)

注解的使用步骤

  1. 在spring配置文件中,声明事务的内容;

    声明事务管理器,说明使用哪个事务管理器对象;

    声明使用注解管理事务,开启注解驱动

  2. 在类的源代码中,加入@Transactional

事务的控制模式:

  1. 编程式,在代码中编程控制事务
  2. 声明式事务,不用编码
步骤一:
<!--声明事务管理器(连接到数据库,做事务提交,事务回滚)-->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
<!--指定数据源-->
<property name="dataSource" ref="myDataSource"/>
</bean> <!--开启事务注解驱动-->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!--最后导入的包是以tx结尾-->
步骤二:

在具体的方法上加上@Transactional注解

	@Transactional(
propagation = Propagation.REQUIRED,
isolation = Isolation.DEFAULT,
readOnly = false,
timeout = 20,
rollbackFor = {NullPointerException.class}
)
@Override
public void buy(Integer goodId, Integer amount) throws Exception {
System.out.println("buy方法的执行");
Sale sale = new Sale();
sale.setGid(goodId);
sale.setNums(amount);
// 生成销售记录
saleDao.insertSale(sale);
// 查询商品
Good good = goodDao.selectById(goodId);
if (good == null){
throw new Exception("商品不存在");
}else if (good.getAmount() < amount){
throw new Exception("库存不足");
}
// 更新库存
Good good1 = new Good();
good1.setId(goodId);
good1.setAmount(amount);
goodDao.updateGood(good1);
System.out.println("buy方法的完成");
}
rollbackFor说明
  1. 框架首先检查方法抛出的异常是不是在rollbackFor数组中,如果在一定会发生回滚;
  2. 如果方法抛出的异常不在rollbackFor数组中,框架会继续检查抛出的异常是不是RuntimrException,如果是RuntimeException,一定会发生回滚。

使用rollbackFor可以实现发生受检查异常时让其发生回滚。

注解的使用特点

直接使用@Transactional会使用默认值

  • spring框架自己提供的事务控制
  • 适合中小型项目,注解都放置在了源代码中,不利于优化
  • 使用方便效率高

使用Aspectj框架在spring配置文件中,声明事务控制

使用aspectj的aop,声明事务控制叫做声明式事务

使用步骤

  1. 加入spring-aspectj的依赖
  2. spring的配置文件声明事务属性
    • 声明事务管理器
    • 声明业务方法需要的事务属性
    • 声明切入点表达式
步骤

基本上是模板化的方法

<!--声明式事务-->
<!--1.声明事务管理器-->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager2">
<property name="dataSource" ref="myDataSource"/>
</bean> <!--2.声明业务方法的事务属性(隔离级别,传播行为,超时)
id:给业务方法配置事务段代码起个名字,唯一值
transaction-manager:事务管理器的id
-->
<tx:advice id="serviceAdvice" transaction-manager="transactionManager2">
<!--给具体的业务方法增加事务的说明-->
<tx:attributes>
<!-- 给具体的业务方法,说明他需要的事务属性
name:业务方法名称,配置name的值 1.业务方法的名称(类中的某一个方法) 2.带有部分通配符的方法名称 3.使用*
propagation:指定传播行为
isolation:隔离级别
read-only:是否只读,默认为false
timeout:超时时间
rollback-for:指定回滚的异常类列表,使用的异常类的全限定名称(多个异常时用都好分割)
-->
<tx:method name="buy"
isolation="DEFAULT"
propagation="REQUIRED"
timeout="20"
rollback-for="java.lang.NullPointerException"
/> <!--在业务方法有命名规则的时候,可以对一些方法使用事务-->
<tx:method name="add*" propagation="REQUIRED" timeout="20" isolation="DEFAULT"/>
<tx:method name="delete*" propagation="REQUIRED" timeout="20" isolation="DEFAULT"/>
<!--以上方法以外的-->
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<!--通过上述方法的声明,但是我们并不知道是哪个类的方法,让上述声明生效的方法:切入点表达式-->
<!--声明切入点表达式:表示哪些包中的哪些类的方法参与事务-->
<aop:config>
<!--声明切入点表达式
expression:切入点表达式,表示哪些类中的哪些方法要参与事务
id:切入点表达式的名称,唯一值
-->
<aop:pointcut id="servicePointCut" expression="execution(* *..service..*.*(..))"/>
<!-- 关联切入点表达式和事务的通知-->
<aop:advisor advice-ref="serviceAdvice" pointcut-ref="servicePointCut"/>
</aop:config>
优缺点
  • 缺点:理解难,配置复杂

  • 优点:代码和事务分开。控制事务源代码不用修改。

    ​ 能快速的了解和掌握项目的全部事务。适合大型项目。

spring事务详解(基于注解和声明的两种实现方式)的更多相关文章

  1. spring事务详解(二)简单样例

    系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.引子 ...

  2. spring事务详解(三)源码详解

    系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.引子 ...

  3. spring事务详解(一)初探事务

    系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 引子 很多 ...

  4. spring事务详解(五)总结提高

    系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.概念 ...

  5. spring事务详解(四)测试验证

    系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.引子 ...

  6. spring事务详解(二)实例

    在Spring中,事务有两种实现方式: 编程式事务管理: 编程式事务管理使用底层源码可实现更细粒度的事务控制.spring推荐使用TransactionTemplate,典型的模板模式. 申明式事务管 ...

  7. Spring、Spring事务详解;使用XML配置事务

    @Transactional可以设置以下参数: @Transactional(readOnly=false) // 指定事务是否只读的 true/false @Transactional(rollba ...

  8. 【转】Spring事务详解

    1.事务的基本原理 Spring事务的本质其实就是数据库对事务的支持,使用JDBC的事务管理机制,就是利用java.sql.Connection对象完成对事务的提交,那在没有Spring帮我们管理事务 ...

  9. Spring 事务详解

    实现购买股票案例: 一.引入JAR文件: 二.开始搭建分层架构---创建账户(Account)和股票(Stock)实体类 Account: ? 1 2 3 4 5 6 7 8 9 10 11 12 1 ...

随机推荐

  1. logback1.3.x配置详解与实践

    前提 当前(2022-02前后)日志框架logback的最新版本1.3.0已经更新到1.3.0-alpha14版本,此版本为非stable版本,相对于最新稳定版1.2.10来说,虽然slf4j-api ...

  2. 记录netcore一次内存暴涨的坑

    项目用到了Coldairarrow/EFCore.Sharding: Database Sharding For EFCore (github.com)这个组件,最初是因为分表做的还不错所以用了它. ...

  3. Ubuntu20.04 PostgreSQL 14 安装配置记录

    PostgreSQL 名称来源 It was originally named POSTGRES, referring to its origins as a successor to the Ing ...

  4. MXNet学习:预测结果-识别单张图片

    用到了model里的FeedForward.load和predict import os import mxnet as mx import numpy as np import Image from ...

  5. 记录一次elasticsearch-5.6.4宕机排查经历

    犯罪现场~~ es: 三节点,配置相同 内存: 248G CPU: 没注意看 磁盘: 2T data: 380G左右 indices: 近9800条 在下才疏学浅,目前跟着大佬学习,这个问题还没解决, ...

  6. HTTP协议和HTTPS协议的那些事

    文章目录 HTTPS VS HTTP HTTPS=HTTP+加密+证书+完整性保护 加密 对称加密 非对称加密 混合加密 证书 完整性保护 HTTPS并不能取代HTTP SSL是把双刃剑 HTTPS的 ...

  7. 我的平安夜-Merry Christmas

    我的平安夜-Merry Christmas 平安夜给自己买的第一个"苹果",嘻嘻. 今夜,不想去学习技术知识点什么的, 我们就想到哪里写哪里,就简单聊聊思维方式吧. 其实我不想做今 ...

  8. BI系统要自研还是采购?这篇文章告诉你

    首先说一下目前市面上的BI工具都有哪些吧.总体上,其实分为免费和付费两大阵营.免费阵营里,为首的当然是GA(也就是谷歌分析).PowerBI,但是由于有墙的限制,很多公司没法使用前者.付费阵营里,近两 ...

  9. 【C# 线程】内存屏障 MemoryBarrier

    背景 同步基元分为用户模式和内核模式 用户模式:Iterlocked.Exchange(互锁).SpinLocked(自旋锁).易变构造(volatile关键字.volatile类.Thread.Vo ...

  10. yalmip安装

    1,将yalmip解压,在matlab中添加路径. 2,yalmiptest测试是否安装成功.