Spring JDBC事务个人理解

Spring JDBC

事务:

数据库执行(查询并可能更新)的基本单元

特性
A-原子性:事务是一个基本单元,要么全部执行要么全都不执行
C-一致性:与原子性相关
I-隔离性:事务间互不干扰
D-持久性:事务一旦提交无法更改
基本原理
流程
{
  1.获取连接
  2.开启事务---设置自动提交true/false
  3.执行sql
  4.提交/回滚
  5.关闭连接
}
临时表的使用  内存临时表memory引擎  磁盘临时表myisam/innodb
{
  进行增删改的时候,数据先进入临时表,检查上下文环境,判断这条sql能不能执行,如果检查ok
  增--由临时表写入
  改--数据由表复制进临时表,检查关联关系ok--替换
  删--数据由表复制进临时表,检查关联关系ok--删除表数据
  查--
  {
  	1.ORDER BY子句和GROUP BY子句不同, 例如:ORDERY BY price GROUP BY name;
	2.在JOIN查询中,ORDER BY或者GROUP BY使用了不是第一个表的列 例如:SELECT * from TableA, TableB ORDER BY TableA.price GROUP by TableB.name
	3.ORDER BY中使用了DISTINCT关键字 ORDERY BY DISTINCT(price)
	4.当group by 索引的时候,当数据量较小的时候不会使用临时表,当数据量(我测试的数据量在30万左右)大的时候会使用临时表
	5.当group by 不是索引的时候会使用临时表
  }
}


@Transactional作用
1.在实例化阶段wrapIfNecessary扫描相关的Advisor(aop的Before/After/Around)以及事务的Transactional

2.判断出如果有Advisor通知则开始创建代理对象

3.对带Transactional注解的方法织入两个方法
{
	1.关闭自动提交--大概是在Before位置
	2.对执行结果进行判断---使用回滚或者提交--大概exit Around/Before位置
}
事务使用

常见使用方法

在这里插入图片描述
在这里插入图片描述

事务嵌套情况
假如service A – methodA 里面有 serviceB – methodB
PROPAGATION_REQUIRED(Spring 默认)
--有事务不起事务,没有事务起事务

如果 ServiceB.MethodB() 的事务级别定义为 PROPAGATION_REQUIRED,那么执行ServiceA.MethodA() 的时候 Spring 已经起了事务,这时调用 ServiceB.MethodB(),ServiceB.MethodB() 看到自己已经运行在 ServiceA.MethodA() 的事务内部,就不再起新的事务。假如 ServiceB.MethodB() 运行的时候发现自己没有在事务中,他就会为自己分配一个事务。这样,在 ServiceA.MethodA() 或者在 ServiceB.MethodB() 内的任何地方出现异常,事务都会被回滚。
PROPAGATION_REQUIRES_NEW
--外层事务挂起,内层事务继续执行,如果外层异常,内层不回滚;如果内层异常,看类型是不是外层会回滚的异常

比如我们设计 ServiceA.MethodA() 的事务级别为 PROPAGATION_REQUIRED,ServiceB.MethodB() 的事务级别为 PROPAGATION_REQUIRES_NEW。那么当执行到 ServiceB.MethodB() 的时候,ServiceA.MethodA() 所在的事务就会挂起,ServiceB.MethodB() 会起一个新的事务,等待 ServiceB.MethodB() 的事务完成以后,它才继续执行。他 与 PROPAGATION_REQUIRED 的 事 务 区 别 在 于 事 务 的 回 滚 程 度 了 。 因 为ServiceB.MethodB() 是 新 起 一 个 事 务 , 那 么 就 是 存 在 两 个 不 同 的 事 务 。 如 果
ServiceB.MethodB() 已 经 提 交 , 那 么 ServiceA.MethodA() 失 败 回 滚 ,ServiceB.MethodB() 是不会回滚的。如果 ServiceB.MethodB() 失败回滚,如果他抛出的异常被 ServiceA.MethodA() 捕获,ServiceA.MethodA() 事务仍然可能提交(主要看 B 抛出的异常是不是 A 会回滚的异常)。
PROPAGATION_SUPPORTS
--外层有事务,内层加入事务,外层没有,内层不开

假设 ServiceB.MethodB() 的事务级别为 PROPAGATION_SUPPORTS,那么当执行到ServiceB.MethodB()时,如果发现 ServiceA.MethodA()已经开启了一个事务,则加入当前的事务,如果发现 ServiceA.MethodA()没有开启事务,则自己也不开启事务。这种时候,内部方法的事务性完全依赖于最外层的事务。
PROPAGATION_NESTED
--比如是多个内层事务方法,如果内层方法失败了,就回滚(相当于没执行),继续执行其他方法。外层方法是否回滚主要看和内层方法异常是否一致,是否可以回滚。

现 在 的 情 况 就 变 得 比 较 复 杂 了 , ServiceB.MethodB() 的 事 务 属 性 被 配 置 为
PROPAGATION_NESTED, 此时两者之间又将如何协作呢? ServiceB.MethodB() 如果 rollback, 那么内部事务(即 ServiceB.MethodB()) 将回滚到它执行前的 SavePoint而外部事务(即 ServiceA.MethodA()) 可以有以下两种处理方式:捕获异常,执行异常分支逻辑这 种 方 式 也 是 嵌 套 事 务 最 有 价 值 的 地 方 , 它 起 到 了 分 支 执 行 的 效 果 , 如 果ServiceB.MethodB()失败, 那么执行 ServiceC.MethodC(), 而 ServiceB.MethodB()已经回滚到它执行之前的 SavePoint, 所以不会产生脏数据(相当于此方法从未执行过), 这 种 特 性 可 以 用 在 某 些 特 殊 的 业 务 中 , 而 PROPAGATION_REQUIRED 和PROPAGATION_REQUIRES_NEW 都没有办法做到这一点。外部事务回滚/提交 代码不做任何修改, 那么如果内部事务(ServiceB.MethodB())rollback, 那么首先 ServiceB.MethodB() 回滚到它执行之前的 SavePoint(在任何情况下都会如此), 外部事务(即 ServiceA.MethodA()) 将根据具体的配置决定自己是commit 还是 rollback。
mandator:支持当前事务,如果没有事务就抛异常
not_supported:非事务执行,有事务就挂起
never:非事务执行,有事务就抛异常
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值