Mybatis的工作原理

无论是Mybatis也好,Spring也罢,它们的执行过程无非可分为启动阶段和运行阶段:

启动阶段:

1. 定义配置文件,如XML,注解 

2. 解析配置文件,将配置文件加载到内存当中

运行阶段:

1. 读取内存中的配置文件,并根据配置文件实现对应的功能

对于执行SQL的逻辑来讲,有如下步骤:

当配置完成之后,假如说我们要执行一个下面一个sql,那么该如何执行呢?

TestMapper testMapper = session.getMapper(TestMapper.class);
Test test = testMapper.findOne(1);

代理类的生成

首先Mybatis会根据我们传入接口通过JDK动态代理,生成一个代理对象TestMapper,生成逻辑如下所示: 

public T newInstance(SqlSession sqlSession) {// mapperProxy实现了Invocationhandler接口,用于JDK动态代理final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);return newInstance(mapperProxy);
}
// 通过JDK动态代理生成对象
protected T newInstance(MapperProxy<T> mapperProxy) {return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}

代理类的主要逻辑在MapperProxy中,而代理逻辑则是通过MapperMethod完成的。

对于MapperMethod来说,它在创建的时候是需要读取XML或者方法注解的配置项,所以在使用的时候才能知道具体代理的方法的SQL内容。同时,这个类也会解析和记录被代理方法的入参和出参,以方便对SQL的查询占位符进行替换,同时对查询到的SQL结果进行转换。

执行SQL

代理类生成之后,就可以执行代理类的具体逻辑,也就是真正开始执行用户自定义的SQL逻辑了。
首先会进入到MapperMethod核心的执行逻辑,如下所示: 

public Object execute(SqlSession sqlSession, Object[] args) {Object result;switch (command.getType()) {case INSERT: {Object param = method.convertArgsToSqlCommandParam(args);result = rowCountResult(sqlSession.insert(command.getName(), param));break;}case UPDATE: {Object param = method.convertArgsToSqlCommandParam(args);result = rowCountResult(sqlSession.update(command.getName(), param));break;}case DELETE: {Object param = method.convertArgsToSqlCommandParam(args);result = rowCountResult(sqlSession.delete(command.getName(), param));break;}case SELECT:if (method.returnsVoid() && method.hasResultHandler()) {executeWithResultHandler(sqlSession, args);result = null;} else if (method.returnsMany()) {result = executeForMany(sqlSession, args);} else if (method.returnsMap()) {result = executeForMap(sqlSession, args);} else if (method.returnsCursor()) {result = executeForCursor(sqlSession, args);} else {Object param = method.convertArgsToSqlCommandParam(args);result = sqlSession.selectOne(command.getName(), param);}break;case FLUSH:result = sqlSession.flushStatements();break;default:throw new BindingException("Unknown execution method for: " + command.getName());}// ...return result;}

通过代码我们可以很清晰的发现,为什么Mybatis的insert,update和delete会返回行数的原因。业务处理上,我们经常通过update==1来判断当前语句是否更新成功。
这里一共做了两件事情,一件事情是通过BoundSql将方法的入参转换为SQL需要的入参形式,第二件事情就是通过SqlSession来执行对应的Sql。下面我们通过select来举例。

缓存

Sqlsession是Mybatis对Sql执行的封装,真正的SQL处理逻辑要通过Executor来执行。Executor有多个实现类,因为在查询之前,要先check缓存是否存在,所以默认使用的是CachingExecutor类,顾名思义,它的作用就是二级缓存。 

二级缓存是和命名空间绑定的,如果多表操作的SQL的话,是会出现脏数据的。同时如果是不同的事务,也可能引起脏读,所以要慎重。
如果二级缓存没有命中则会进入到BaseExecutor中继续执行,在这个过程中,会调用一级缓存执行。
值得一提的是,在Mybatis中,缓存分为PerpetualCache, BlockingCache, LruCache等,这些cache的实现则是借用了装饰者模式。一级缓存使用的是PerpetualCache,里面是一个简单的HashMap。一级缓存会在更新的时候,事务提交或者回滚的时候被清空。换句话说,一级缓存是和SqlSession绑定的。

查询数据库

如果一级缓存中没有的话,则需要调用JDBC执行真正的SQL逻辑。我们知道,在调用JDBC之前,是需要建立连接的

处理查询结果

当我们获取到查询结果之后,就需要对查询结果进行封装,即把查询到的数据库字段映射为DO对象。
因为此时我们已经拿到了执行结果ResultSet,同时我们也在应用启动的时候在配置文件中配置了DO到数据库字段的映射ResultMap,所以通过这两个配置就可以转换。核心的转换逻辑是通过TypeHandler完成的,流程如下所示:
1. 创建返回的实体类对象,如果该类是延迟加载,则先生成代理类
2. 根据ResultMap中配置的数据库字段,将该字段从ResultSet取出来
3. 从ResultMap中获取映射关系,如果没有,则默认将下划线转为驼峰式命名来映射
4. 通过setter方法反射调用,将数据库的值设置到实体类对象当中

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

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

相关文章

RJ45网口模块设计

1、以太网概述及RJ45实物 2、常用网口信号介绍 3、RJ45网口布局布线要点分析 4、总结 1、变压器下面需要进行挖空处理&#xff0c;以免底下的铜引入干扰&#xff0c;&#xff08;将多边形挖空区域的所在层设置为Multi-Layer多层&#xff09; 2、为了更直观的看一个类中线的长…

Metagenome宏基因组,未识别的物种unclassified

1&#xff1a;"Bacteria|Proteobacteria|Betaproteobacteria|Neisseriales|Neisseriaceae|Kingella" 2&#xff1a;"Bacteria|Proteobacteria|Betaproteobacteria|Neisseriales|Neisseriaceae|unclassified" # 未识别到的/未注解到的…

深度学习笔记1:神经网络与模型训练过程

参考博客&#xff1a;PyTorch深度学习实战&#xff08;1&#xff09;——神经网络与模型训练过程详解_pytorch 实战-CSDN博客 人工神经网络 ANN&#xff1a;张量及数学运算的集合&#xff0c;排列方式近似于松散的人脑神经元排列 组成 1&#xff09;输入层 2&#xff09;隐…

【多模态】从零学习多模态——2024学习笔记总结

从零学习多模态——2024学习笔记总结 前言1. preliminary2. Transformer和NLP基础3. 多模态模型原理和架构学习4. 动手实验多模态模型第一步尝试Swift框架使用数据验证 5. 总结 前言 2024快结束啦&#xff0c;半年抽空学了学多模态还挺好玩的&#xff0c;学习和踩坑记录记一下&…

CAT3D: Create Anything in 3D with Multi-View Diffusion Models 论文解读

24年5月的论文&#xff0c;上一版就是ReconFusion 目录 一、概述 二、相关工作 1、2D先验 2、相机条件下的2D先验 3、多视角先验 4、视频先验 5、前馈方法 三、Method 1、多视角扩散模型 2、新视角生成 3、3D重建 一、概述 该论文提出一种CAT3D方法&#xff0c;实现…

Python中构建终端应用界面利器——Blessed模块

在现代开发中&#xff0c;命令行应用已经不再仅仅是一个简单的文本输入输出工具。随着需求的复杂化和用户体验的重视&#xff0c;终端界面也逐渐成为一个不可忽视的设计环节。 如果你曾经尝试过开发终端UI&#xff0c;可能对传统的 print() 或者 input() 函数感到不满足&#…

5.若依的角色权限控制

RBAC 基于角色的访问控制&#xff0c;通过角色来分配和管理用户的菜单权限。 修改课程管理的菜单到主类目下 新建角色并分配菜单 新建用户并分配角色 添加一个根菜单&#xff0c;父级为主类目

flutter插件开发-ios

flutter插件开发是一个重要的技能&#xff0c;拓展flutter与原生的通信&#xff0c;将一些公用的东西封装&#xff0c;给不同的项目使用。 阅读前置&#xff1a; flutter基本通道调用 objective-c基础语法 ios项目基础知识 目录 1、创建一个插件项目2、项目结构3、编写原生代码…

手机租赁平台开发全攻略打造高效便捷的租赁服务系统

内容概要 手机租赁平台开发&#xff0c;简单说就是让用户能轻松租赁各类手机的高效系统。这一平台不仅帮助那些想要临时使用高端手机的人们节省了不少资金&#xff0c;还为商家开辟了新的收入渠道。随着智能手机的普及&#xff0c;很多人并不需要长期拥有一部手机&#xff0c;…

【从零开始入门unity游戏开发之——C#篇34】C#匿名函数(delegate )和Lambda表达式

文章目录 一、匿名函数&#xff08;delegate &#xff09;1、什么是匿名函数&#xff1f;2、匿名函数的基本语法2.1 语法2.2 **没有参数的匿名函数&#xff1a;**2.3 **有参数的匿名函数&#xff1a;**2.4 **有返回值的匿名函数&#xff1a;** 3、匿名函数的使用示例3.1 作为参…

echarts没有map地图解决方案

在echarts4.9以后的版本中移除了map地图 使用命令npm install echarts --save它会下载最新版本 的echarts 所有我们要下载回echarts4.9版本中 如果已经下载了最新的可以卸载 // 卸载echarts运行&#xff1a; npm uninstall echarts然后再去下载4.9版本 // 安装4.9版本的ech…

WebP Vs. PNG:哪种图像格式适合您的网站?

图像对任何网站都至关重要,可以增强视觉吸引力和用户体验。但是,图像也会显着影响网站的加载时间,因此必须针对 Web 使用对其进行优化。一种方法是使用正确的图像格式。

【Git】—— 代码版本控制工具git的安装及基本使用

目录 一、Git的核心作用 二、安装Git 三、本地仓库命令 1、初始化 2、查看文件状态 3、将文件添加到暂存区 4、将文件提交到本地仓库 5、查看提交日志 6、将暂存区文件取消暂存 7、回溯到指定版本 四、忽略文件 一、Git的核心作用 远程备份&#xff1a;将代码备份到…

sentinel-请求限流、线程隔离、本地回调、熔断

请求限流&#xff1a;控制QPS来达到限流的目的 线程隔离&#xff1a;控制线程数量来达到限流的目录 本地回调&#xff1a;当线程被限流、隔离、熔断之后、就不会发起远程调用、而是使用本地已经准备好的回调去提醒用户 熔断&#xff1a;熔断也叫断路器&#xff0c;当失败、或者…

阿里云人工智能ACA(七)——计算机视觉基础

一、自然语言处理基本介绍 1. 自然语言处理的定义 1-1 自然语言 人类使用的在社会生活中自然形成的语言 1-2 自然语言处理 目标是让计算机能够理解、解析、生成和处理人类的自然语言 包含自然语言理解和自然语言生成两部分组成 2. 自然语言处理的发展趋势 3.自然语言处理…

细说STM32F407单片机通过IIC读写EEPROM 24C02

目录 一、操作说明 二、工程配置 1、时钟、DEBUG、GPIO、USART6、NVIC、Code Generator 2、 IIC2 &#xff08;1&#xff09;Master Features组&#xff0c;主设备参数 &#xff08;2&#xff09;Slave Features组&#xff0c;从设备参数 三、软件设计 1、KELED 2、E…

redis开发与运维-redis04-redis客户端Jedis与连接池及客户端异常模拟

文章目录 【README】【1】redis客户端通信协议【2】java客户端Jedis连接redis集群【2.1】Jedis基本用法【2.2】Jedis操作5种数据类型代码实践【2.3】Jedis使用序列化api操作【2.3.1】操作Jedis字节数组api代码实践 【3】Jedis连接池【3.1】Jedis连接池JedisPool代码实践【3.1.1…

KaiOS 4.0 | DataCall and setupData implemention

相关文档 1、KaiOS 3.1 系统介绍 KaiOS 系统框架和应用结构(APP界面逻辑)文章浏览阅读842次,点赞17次,收藏5次。对于Java开发者而言,理解JS的逻辑调用是有点困难的。而KaiOS webapp开发又不同于现代的web开发,更像chrome浏览器内嵌模式。在这里梳理一下kaios平台web应用…

正则化强度的倒数C——让模型学习更准确

引言 嘿&#xff0c;小朋友们&#xff0c;今天我们要学习一个叫做正则化强度倒数C的概念。这听起来可能有点复杂&#xff0c;但它其实是一种帮助计算机学习的方法。想象一下&#xff0c;我们教计算机识别动物&#xff0c;我们希望它既能识别出猫&#xff0c;也能识别出狗&…

飞牛NAS登录Fn Connect教程实测|远程访问教程

前言 有很多小伙伴已经用上飞牛NAS系统很久了&#xff0c;但大部分都是在局域网下使用&#xff0c;如果外出办公或者在办公室&#xff0c;就没办法连接到家里的NAS。 于是咱们今天先出一条关于远程连接到飞牛NAS的教程。 关于飞牛NAS的教程会一步步发布&#xff0c;请耐心等…