4. Mybatis 事务和Spring事务关系

大体上分为两种情况:方法上添加了事务注解@Transactional 和方法上没有添加事务注解@Transactional。

  • 添加了@Transactional 注解的在注入 bean 的时候就会被创建代理类,在代理类中使用增强逻辑进行事务处理。
  • 没有添加@Transactional 注解的,在 SqlSession 执行 sql方法的时候,执行完sql 后提交事务。

方法上没有事务注解@Transactional

我们需要知道大体流程:

  1. 与Spring 框架集成后的 mybatis 的 SqlSession 会被SqlSessionTemplate代理。即当我们使用 mybatis 执行 sql 的时候必然会走 SqlSessionTemplate 的 invoke 方法
  2. 在SqlSessionTemplate的 invoke 方法中。会先获取一个 Session 然后在执行被代理的方法(执行增删改查的sql)。
  3. 执行完Sql 之后会判断是否有Spring事务,如果没有Spring事务就提交。如果有 Spring 事务,当前 invoke 方法什么也不做,事务交给 Spring 事务管理器来做。

这个时候sql 执行完自动提交。SQL 执行失败就失败。这个时候 sql 的执行会走SqlSession 的代理逻辑 SqlSessionTemplate 中的invoke 方法。

image

方法上有事务注解@Transactional

这个时候会用到 Spring 的事务管理器。

当然首先是 AOP 针对@Transactional 注解进行代理。在 AOP 的 BeanPostProcessor 扫描@Transactional 注解的时候,会解析目标类和方法的属性并包装成事务属性对象,并对含有 Transactional 注解的类创建动态代理对象。

动态代理对象的增强逻辑或者叫代理逻辑为TransactionInterceptor。

此外我们还需要知道:

Mybatis事务和Spring事务的沟通桥梁就是 TransactionSynchronizationManager。TransactionSynchronizationManager会和DataSourceTransactionManager进行交互。

Transactional的代理逻辑

入口是TransactionInterceptor​,TransactionInterceptor 本身是个Advisice。是AOP的切面。其切面逻辑主要是调用抽象父类TransactionAspectSupport的invokeWithinTransaction​这个方法(以事务的方式调用这个方法)。

  1. 获取AnnotationTransactionAttributeSource​ 事务属性源。

  2. 获取事务属性,从事务属性源里获取当前被调用方法的事务属性。

  3. 获取事务管理器。根据事务管理器的类型选择对应的逻辑执行。

  4. 获取事务唯一标识: joinpointIdentification​ 这个算是事务的唯一key吧。通常是类的全路径名+方法名

  5. 创建一个事务:如果该方法对应的事务属性不为空,调用createTransactionIfNecessary​方法。该方法未必会一定创建事务,如果事务存在就不会创建事务。

    1. 如果事务存在,调用getTransaction​获取已存在的事务。并按照事务传播机制进行处理

      1. PROPAGATION_NEVER​:抛异常
      2. PROPAGATION_NOT_SUPPORTED​:挂起当前事务
      3. PROPAGATION_REQUIRES_NEW​:挂起当前事务,开启一个新的事务
      4. 。。。
    2. 处理事务超时时间

    3. 如果没有发现已存在的事务,处理传播机制。

      1. startTransaction开始执行事务:PROPAGATION_REQUIRED

        1. doBegin方法中将事务自动提交改为false。
  6. invocation.proceedWithInvocation()执行增强方法(环绕通知);

  7. 如果事务方法执行未发生异常,则调用commitTransactionAfterReturning(txInfo)进行提交事务;

  8. 如果事务方法执行发生异常,则调用completeTransactionAfterThrowing(txInfo, ex)进行异常回滚;

Mybatis ->TransactionSynchronizationManager

Mybatis事务和Spring事务的沟通桥梁就是 TransactionSynchronizationManager。TransactionSynchronizationManager会和DataSourceTransactionManager进行交互。

我们先看一下mybatis是如何和TransactionSynchronizationManager对接的。一切都在SqlSessionTemplate这个类的反射逻辑中。

SqlSessionTemplate

SqlSessionTemplate禁用掉了手动事务操作。

public void commit(boolean force) {throw new UnsupportedOperationException("Manual commit is not allowed over a Spring managed SqlSession");
}public void rollback() {throw new UnsupportedOperationException("Manual rollback is not allowed over a Spring managed SqlSession");
}
获取sqlSession的逻辑

在MybatisAutoConfiguration中创建了SqlSessionTemplate代理DefaultSqlSession以实现DefaultSqlSession的复用。

SqlSessionTemplate是SqlSession的实现之一。其目的主要是适应Spring的容器化环境和Spring 事务。

在SqlSessionTemplate的代理逻辑中会有获取 SqlSession的逻辑。这里会优先从TransactionSynchronizationManager获取一个SqlSession。如果获取不到,再创建一个并注册到TransactionSynchronizationManager中。下次直接用就可以。

public static SqlSession getSqlSession(SqlSessionFactory sessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) {Assert.notNull(sessionFactory, "No SqlSessionFactory specified");Assert.notNull(executorType, "No ExecutorType specified");SqlSessionHolder holder = (SqlSessionHolder)TransactionSynchronizationManager.getResource(sessionFactory);SqlSession session = sessionHolder(executorType, holder);if (session != null) {return session;} else {LOGGER.debug(() -> {return "Creating a new SqlSession";});session = sessionFactory.openSession(executorType);registerSessionHolder(sessionFactory, executorType, exceptionTranslator, session);return session;}
}
判断sqlSession是否支持事务
public static boolean isSqlSessionTransactional(SqlSession session, SqlSessionFactory sessionFactory) {Assert.notNull(session, "No SqlSession specified");Assert.notNull(sessionFactory, "No SqlSessionFactory specified");SqlSessionHolder holder = (SqlSessionHolder)TransactionSynchronizationManager.getResource(sessionFactory);return holder != null && holder.getSqlSession() == session;
}

DataSourceTransactionManager -> TransactionSynchronizationManager

DataSourceTransactionManager 是Spring事务中事务管理器​PlatformTransactionManager​的一种实现。

PlatformTransactionManager有三个方法分别是:getTransaction、commit、rollback。由于getTransaction最为简洁直观,所以我们单看这个类就可以。

protected Object doGetTransaction() {DataSourceTransactionObject txObject = new DataSourceTransactionObject();txObject.setSavepointAllowed(isNestedTransactionAllowed());ConnectionHolder conHolder =(ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());txObject.setConnectionHolder(conHolder, false);return txObject;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/623393.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【JaveWeb教程】(26) Mybatis基础操作(新增、修改、查询、删除) 详细代码示例讲解(最全面)

目录 1. Mybatis基础操作1.1 需求1.2 准备1.3 删除1.3.1 功能实现1.3.2 日志输入1.3.3 预编译SQL1.3.3.1 介绍1.3.3.2 SQL注入1.3.3.3 参数占位符 1.4 新增1.4.1 基本新增1.4.2 主键返回 1.5 更新1.6 查询1.6.1 根据ID查询1.6.2 数据封装1.6.3 条件查询1.6.4 参数名说明 1. Myb…

如何打赢稳定性之战?

文章目录 前言为什么总会出现问题呢?如何证明你的稳定性做的有效果?既是持久战,也是防御战1. 提前建筑好防御工事2. 以攻为守3. 找外部支援和配合 前言 随着23年年末期间,各大厂争先恐后的出现的各种线上故障,一时间“…

帆软使用总结-动态分组背景变色

1.开发界面设计 提示: ROUNDUP((ROW() - M) / N, 0) % 2 0row() 获取当前行号 M 标题行数 N 间隔行数 ROUNDUP() 向上取整 如果被2整除,改变背景颜色 当前公式:ROUNDUP((ROW() - 2) / 3, 0) % 2 02.效果演示

【题解】—— 每日一道题目栏

2024.1 【题解】—— LeetCode一周小结1 1. 1599. 经营摩天轮的最大利润 2. 466. 统计重复个数 3. 2487. 从链表中移除节点 4. 2397. 被列覆盖的最多行数 5. 1944. 队列中可以看到的人数 6. 2807. 在链表中插入最大公约数 7. 383. 赎金信 【题解】—— LeetCode一周小…

【前端框架】Vue2合集

一、Vue快速上手 1、Vue概念 vue 是一个用于构建用户界面的渐进式框架&#xff0c;由数据驱动 vue 的两种使用方式 vue 核心包开发&#xff1a;局部模块改造vue 核心包与 vue 插件 工程化开发&#xff1a;整站 开发 2、 创建实例 1、准备容器 <div id"app"&…

网站万词霸屏推广系统源码:实现关键词推广,轻松提高关键词排名,带完整的安装部署教程

现如今&#xff0c;互联网的快速发展&#xff0c;网站推广成为企业网络营销的重要手段。而关键词排名作为网站推广的关键因素&#xff0c;一直备受关注。罗峰给大家分享一款网站万词霸屏推广系统源码&#xff0c;该系统可实现关键词推广&#xff0c;有效提高关键词排名&#xf…

【教3妹学编程-算法题】回文串重新排列查询

3妹&#xff1a;好冷啊&#xff0c; 冻得瑟瑟发抖啦 2哥 : 这已经是你今年的第几次抖啦&#xff1f; 3妹&#xff1a;昨天20度&#xff0c;今天7度&#xff0c;直降13度呢&#xff0c;能不抖嘛 2哥 : 继哈尔滨之后&#xff0c;全国各地的城市也在发展旅游业。 河北喊话赵丽颖回…

使用mamba替换conda和anaconda配置环境安装软件

使用mamba替换miniconda和anaconda&#xff0c;原因是速度更快&#xff0c;无论是创建新环境还是激活环境 conda、mamba、anaconda都是蟒蛇的意思… 下载mambaforge wget https://github.com/conda-forge/miniforge/releases/latest/download/Mambaforge-Linux-x86_64.sh ba…

乐意购项目前端开发 #3

一、icon的使用 前往网站挑选要的图标 iconfont-阿里巴巴矢量图标库https://www.iconfont.cn/?spma313x.manage_type_myprojects.i3.2.2f173a81fQSVOU 创建项目添加图标 选择Font Class 下载到本地 解压后会看到这个页面 在asserts目录下创建iconfont目录,然后将最底下的6…

数据库第一次作业

1.创建一个英雄表 create table t_hero ( id int primary key auto_increment, name varchar(10) unique not null, gender char(5) check (gender in (男,女)), grade char(5) default 5星, groups char(5) check (groups in (毁灭,巡猎,智识,存护,…

GPT与文心一言大模型的比较与展望

目录 前言1 GPT和文心一言简介2 GPT和文心一言的技术原理和基础架构3 GPT和文心一言的模型规模和参数数量4 GPT和文心一言的语言理解表现5 展望GPT和文心一言未来的发展5.1 技术改进5.2 应用扩展 结语 前言 随着人工智能技术的飞速发展&#xff0c;自然语言处理领域的两个引领…

swing快速入门(四十四)拖动、编辑JTree结点

注释很详细&#xff0c;直接上代码 新增内容&#xff08;源码细节知识点巨多&#xff0c;建议细看&#xff09; 1.设置JTree可编辑 2.使用JTree关联的数据模型实现节点的增删改 3.鼠标拖动节点事件设计及处理方法 4.手动刷新视图与自动刷新的方法区别 5.自定位节点视图方法 源码…

linux环境中一次启动多个jar包,并且设置脚本开机自启

1、编写启动脚本 我们在通过jar启动项目时&#xff0c;有时候会比较多&#xff0c;启动会比较麻烦&#xff0c;需要编写shell脚本启动&#xff0c;将启动脚本存放在需要启动的jar包路径下。&#xff08;文档存放在 /home/process_parent &#xff09; vim start.sh#! /bin/sh…

【python】11.文件和异常

文件和异常 实际开发中常常会遇到对数据进行持久化操作的场景&#xff0c;而实现数据持久化最直接简单的方式就是将数据保存到文件中。说到“文件”这个词&#xff0c;可能需要先科普一下关于文件系统的知识&#xff0c;但是这里我们并不浪费笔墨介绍这个概念&#xff0c;请大…

Vue报错 Cannot find module ‘../../modules/es6.symbol‘解决办法

在进行webpack打包的时候&#xff0c;会出现Cannot find module XXX’的错误&#xff0c;找不到某个模块的错误&#xff0c;今天给出解决方法&#xff1a; 直接进行npm install重新打包&#xff1b;如果npm install重新打包之后&#xff0c;仍然出现这个问题&#xff0c;可以进…

NLP论文阅读记录 - 2021 | WOS 智能树提取文本摘要深度学习

文章目录 前言0、论文摘要一、Introduction1.1目标问题1.2相关的尝试1.3本文贡献 二.前提三.本文方法四 实验效果4.1数据集4.2 对比模型4.3实施细节4.4评估指标4.5 实验结果4.6 细粒度分析 五 总结思考 前言 An Intelligent Tree Extractive Text Summarization Deep Learning …

迁移mysql8.x数据到monggodb数据库

因流量逐步增加随即数据库要从mysql换成monggodb&#xff0c;所以有了数据迁移的需求 首先需要导出mysql的数据&#xff0c;导出格式为.CSV的文件 使用navicat链接mysql数据库注意&#xff0c;需要使用拥有所有权限的用户 登录mysql mysql -u root -pZxcvbnm2024 CREATE USER …

实战指南:如何在Spring Boot中无缝整合Dubbo【四】

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 实战指南&#xff1a;如何在Spring Boot中无缝整合Dubbo【四】 前言项目结构主项目(作为主pom)接口服务提供者properties文件实现类 服务消费者properties接口层 实现效果图 前言 微服务架构已经成为…

BUUCTFMisc (我flag呢???)

刚好&#xff0c;更完密码学&#xff0c;然后就到下一个对新手还算 “友好” 的地方了--->Misc&#xff08;但他还是比密码学难&#xff09; 找不出flag belike &#xff1a; 看了别人的找法以后be like&#xff1a; 这里我就来讲几道我觉得比较有意思的题目吧&…

python 字符串的详细处理方法

当前版本&#xff1a; Python 3.8.4 简介 字符串是由字符组成的序列&#xff0c;可以用单引号、双引号或三引号&#xff08;单引号或双引号的连续使用&#xff09;括起来。一般用来表示和处理文本信息&#xff0c;可以是字母、数字、标点符号以及其他特殊字符&#xff0c;用于…