使用 Mybatis 时,调用 DAO接口时是怎么调用到 SQL 的?

Mybatis 是一个流行的 Java 持久层框架,它提供了一种半自动的 SQL 映射方式,允许开发者在 Java 代码中以一种更加直观和灵活的方式来操作数据库。当你使用 Mybatis 调用 DAO 接口时,背后的工作流程大致如下:

  1. 接口定义:首先,你需要定义一个 DAO 接口,这个接口中会包含一些方法,这些方法对应于你想要执行的数据库操作。

  2. Mapper XML:对于 DAO 接口中的每一个方法,你需要在 Mybatis 的映射文件(通常是一个 XML 文件)中定义一个 <mapper> 标签,里面包含一个 <select><insert><update><delete> 标签,对应于你想要执行的 SQL 语句。

  3. 配置文件:在 Mybatis 的配置文件(通常是 mybatis-config.xml)中,你需要指定你的 Mapper XML 文件的位置,这样 Mybatis 才能找到并加载它们。

  4. SqlSessionFactory:Mybatis 使用 SqlSessionFactory 来创建 SqlSession 对象。SqlSessionFactory 是通过配置文件和映射文件构建的,它包含了所有必要的信息来执行 SQL 语句。

  5. SqlSession:SqlSession 是 Mybatis 中执行 SQL 语句的主要对象。它提供了执行 SQL 语句的方法,例如 selectOne、selectList、insert、update 和 delete 等。

  6. 调用 DAO 接口:当你调用 DAO 接口中的方法时,实际上是 Mybatis 的动态代理机制在起作用。Mybatis 会为 DAO 接口创建一个代理对象,当调用接口中的方法时,代理对象会拦截这些调用,然后根据方法名找到对应的 SQL 映射语句,并执行。

  7. 执行 SQL:Mybatis 通过代理对象,使用 SqlSession 来执行对应的 SQL 语句。执行完成后,SqlSession 会返回结果给调用者。

  8. 关闭 SqlSession:执行完毕后,应该关闭 SqlSession 以释放数据库连接资源。

这个过程涉及到了 Mybatis 的核心组件和工作流程,确保了 SQL 语句的执行和结果的返回。使用 Mybatis 的好处之一就是它允许开发者以一种声明式的方式来编写 SQL,同时还能保持代码的清晰和易于维护。

Mybatis 的内部实现细节非常丰富,下面我将通过一些关键类的源码片段来具体展示 Mybatis 的工作原理。

  1. 配置解析(XMLConfigBuilder.java)

Mybatis 使用 XMLConfigBuilder 来解析 mybatis-config.xml 文件:

public Configuration parse() {parseConfiguration(parser.eval(Configuration.class));return configuration;
}

这里,parseConfiguration 方法会填充 Configuration 对象的属性,比如数据库连接信息、类型别名、类型处理器等。
2. 创建 SqlSessionFactory(SqlSessionFactoryBuilder.java)

使用 XMLConfigBuilder 解析配置后,SqlSessionFactoryBuilder 会创建 SqlSessionFactory:

public SqlSessionFactory build(InputStream inputStream) {try {XMLConfigBuilder xmlParser = new XMLConfigBuilder(inputStream, environment, reporter);return build(xmlParser.parse());} catch (Exception e) {throw new BuilderException("Error building SqlSession.", e);}
}
  1. SqlSession 管理(DefaultSqlSessionFactory.java)

DefaultSqlSessionFactory 提供了创建 SqlSession 的方法:

public SqlSession openSession() {return openSessionFromDataSource(configuration.getEnvironment().getDataSource(), null, false);
}
  1. Executor 执行器(BaseExecutor.java)

BaseExecutor 是 Executor 接口的抽象实现,提供了事务和缓存管理的框架:

public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) {ErrorContext.instance().resource(ms.getResource()).activity("querying").object(ms.getId());if (closed) {throw new ExecutorException("Executor was closed.");}if (queryStack == 0 && ms.isFlushCacheRequired()) {clearLocalCache();}List<E> list;try {queryStack++;list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;if (list != null && resultHandler != null) {resultHandler.handleRows(list);}if (list == null) {list = doQuery(ms, parameter, rowBounds, resultHandler, key, boundSql);}} finally {queryStack--;}return list;
}
  1. 动态代理(MapperProxy.java)

MapperProxy 使用 JDK 动态代理来拦截 Mapper 接口方法的调用:

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if (Object.class.equals(method.getDeclaringClass())) {try {return method.invoke(this, args);} catch (Throwable t) {throw new RuntimeException("Error when attempting to invoke method '" +method.getName() + "' on Mapper Proxy.", t);}} else {return mapperMethod.execute(sqlSession, args);}
}
  1. 映射器 XML 解析(XMLMapperBuilder.java)

XMLMapperBuilder 负责解析 Mapper 的 XML 文件:

public void parse() {if (!configuration.isResourceLoaded(resource)) {configurationElement(parser.evalNode("mapper"));configuration.addLoadedResource(resource);bindMapperForNamespace();}
}
  1. 缓存机制(PerpetualCache.java)

PerpetualCache 是 Mybatis 缓存的基本实现:

public V get(Object key, CacheProvider provider) {V value = (V) cache.get(key);if (value == null) {value = provider.apply(key);cache.put(key, value);}return value;
}
  1. TypeHandler 和 ParameterHandler

TypeHandler 接口定义了 Java 类型和 JDBC 类型之间的转换逻辑:

public interface TypeHandler<T> {void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;T getResult(ResultSet rs, int columnIndex) throws SQLException;T getResult(CallableStatement cs, int columnIndex) throws SQLException;
}

ParameterHandler 负责将方法参数映射到 SQL 语句的参数上:

public void setParameters(PreparedStatement ps) throws SQLException {for (ParameterMapping parameter : boundSql.getParameterMappings()) {if (parameter.getMode() != ParameterMode.OUT) {Object value = parameter.getObject(value);TypeHandler typeHandler = parameter.getTypeHandler();typeHandler.setParameter(ps, parameter.getI(), value, parameter.getJdbcType());}}
}
  1. 结果映射(DefaultResultSetHandler.java)

DefaultResultSetHandler 负责将 ResultSet 中的数据映射到 Java 对象:

public <E> List<E> handleRowValues(ResultSet rs, List<E> resultList, RowBounds rowBounds) throws SQLException {if (hasResultSetData(rs)) {int offset = rowBounds == null || rowBounds.getOffset() == RowBounds.NO_ROW_OFFSET ? 0 : rowBounds.getOffset();int limit = rowBounds == null || rowBounds.getLimit() == RowBounds.NO_ROW_LIMIT ? Integer.MAX_VALUE : rowBounds.getLimit();int rowNumber = 0;while (rs.next()) {if (offset > 0) {offset--;continue;}if (limit > 0) {limit--;if (limit == 0) {break;}}Object rowValue = getRowValue(rs, null);resultList.add((E) rowValue);rowNumber++;}}return resultList;
}

这些代码片段展示了 Mybatis 核心组件的工作原理。然而,由于 Mybatis 的复杂性,这里只提供了部分关键代码的简要概述。要完全理解 Mybatis 的内部实现,需要深入研究每个类和接口的实现细节,以及它们之间的交互。关注威哥爱编程,一起向全栈出发。

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

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

相关文章

科普文:一文搞懂jvm实战(二)Cleaner回收jvm资源

概叙 在JDK9中新增了Cleaner类&#xff0c;该类的作用是用于替代finalize方法&#xff0c;更有效地释放资源并避免内存泄漏。 在JEP260提案中&#xff0c;封装了大部分Sun包内部的API之余&#xff0c;还引入了一些新的API&#xff0c;其中就包含着Cleaner这个工具类。Cleaner承…

JavaScript——对象的创建

目录 任务描述 相关知识 对象的定义 对象字面量 通过关键字new创建对象 通过工厂方法创建对象 使用构造函数创建对象 使用原型(prototype)创建对象 编程要求 任务描述 本关任务&#xff1a;创建你的第一个 JavaScript 对象。 相关知识 JavaScript 是一种基于对象&a…

python最基础

基本的类 python最基础、最常用的类主要有int整形&#xff0c;float浮点型&#xff0c;str字符串&#xff0c;list列表&#xff0c;dict字典&#xff0c;set集合&#xff0c;tuple元组等等。int整形、float浮点型一般用于给变量赋值&#xff0c;tuple元组属于不可变对象&#…

Linux网络 namespaces与Docker网络隔离技术

Linux网络命名空间&#xff08;Network Namespaces&#xff09;是Linux内核中一项重要的隔离技术&#xff0c;它允许系统中存在多个完全独立的网络栈&#xff0c;每个网络栈有自己的网络设备、IP地址、路由表、网络接口、防火墙规则等&#xff0c;从而在不同的命名空间之间实现…

面向物联网行业的异常监控追踪技术解决方案:技术革新与运维保障

在现代高度数字化和互联的环境中&#xff0c;物联网技术已经深入到我们生活的方方面面。特别是在家庭和工业环境中&#xff0c;物联网系列通讯作为连接各类设备的关键枢纽&#xff0c;其稳定性和可靠性显得尤为重要。本文将介绍一种创新的监控系统&#xff0c;旨在实时跟踪和分…

MySQL数据库的主从复制与读写分离

一、MySQL数据库的主从复制 1.主从复制的概述及原理 &#xff08;1&#xff09;主从复制的意义 在实际的生产环境中&#xff0c;如果对数据库的读和写都在同一个数据库服务器中操作,无论是在安全性、高可用性还是高并发等各个方面都是完全不能满足实际需求的。因此&#xff…

MySQL入门学习-备份与恢复.数据导入和导出

一、MySQL 提供了多种数据备份和恢复的方法&#xff0c;每种方法都有其特点和适用场景。以下是一些常见的备份和恢复方法及它们的特点&#xff1a; 1. 使用 mysqldump 工具进行逻辑备份&#xff1a; - mysqldump 是最常用的 MySQL 备份工具之一&#xff0c;它可以将数据库中的…

使用Java实现智能物流管理系统

使用Java实现智能物流管理系统 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将探讨如何使用Java语言实现智能物流管理系统&#xff0c;这是一个涉及到…

C语言使用先序遍历创建二叉树

#include<stdio.h> #include<stdlib.h>typedef struct node {int data;struct node * left;struct node * right; } Node;Node * createNode(int val); Node * createTree(); void freeTree(Node * node);void preOrder(Node * node);// 先序创建二叉树 int main()…

【高性能服务器】多进程并发模型

&#x1f525;博客主页&#xff1a; 我要成为C领域大神&#x1f3a5;系列专栏&#xff1a;【C核心编程】 【计算机网络】 【Linux编程】 【操作系统】 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 本博客致力于知识分享&#xff0c;与更多的人进行学习交流 对于常见的C/S模型…

【深度学习】注意力机制的改进:稀疏注意力、局部注意力、低秩/线性注意力

文章目录 稀疏注意力PVT v2中的稀疏注意力公式 代码示例 局部注意力局部注意力Swin Transformer中的基于窗口的注意力公式 代码示例窗口移位操作&#xff08;Shifted Window&#xff09;实现细节公式代码示例 低秩/线性注意力低秩/线性注意力Linformer公式 代码示例代码解释 稀…

事务的影子拷贝-系统架构师(二十)

1、&#xff08;重点&#xff09;企业信息集成按照组织范围分为企业内部的信息集成和外部信息集成。在企业内部信息集成中&#xff0c;&#xff08;&#xff09;实现了不同系统之间的互操作&#xff0c;使的不同系统之间能够实现数据和方法的共享。&#xff08;&#xff09;实现…

Unity小知识

1.当我们把摄像机的内容渲染到RenderTexture上而不是屏幕上时,那么相机的Aspect默认会设置成和RenderTexture的分辨率一样.不过最终如果把RenderTexture作为贴图贴到模型上去的时候还是会被UV拉伸和缩小的。 2.要想自定义UnityPackage的内容&#xff0c;只要找到UnityProject/L…

H5与小程序:两者有何不同?

H5&#xff0c;即HTML5&#xff0c;是构建Web内容的一种语言描述方式&#xff0c;也是互联网的下一代标准&#xff0c;被认为是互联网的核心技术之一。HTML5是在HTML4.01的基础上进行了一定的改进后的规范&#xff0c;用户在使用任何手段进行网页浏览时看到的内容原本都是HTML格…

GPT对话代码库——HAL库下 USART 的配置及问题(STM32G431CBT6)

目录 1&#xff0c;问&#xff1a; 1&#xff0c;答&#xff1a; 示例代码 正确的HAL库初始化方式 自定义初始化方式&#xff08;不推荐&#xff09; 总结 2&#xff0c;问&#xff1a; 2&#xff0c;答&#xff1a; 代码详细解释 初始部分 主初始化部分 初始化调用…

QT学习积累——如何提高Qt遍历list的效率

目录 引出Qt遍历list提高效率显示函数的调用使用&与不使用&除法的一个坑 总结自定义信号和槽1.自定义信号2.自定义槽3.建立连接4.进行触发 自定义信号重载带参数的按钮触发信号触发信号拓展 lambda表达式返回值mutable修饰案例 引出 QT学习积累——如何提高Qt遍历list…

python 操作网页

使用selenium库获取网页元素的属性值是一个常见的需求。以下是一个Python代码示例,展示了如何使用selenium来获取一个链接的href属性以及一个输入框的value属性。 首先,请确保您已经安装了selenium库,并且配置了WebDriver(如ChromeDriver)以驱动浏览器。 pythonfrom sele…

如何避免Java中的内存泄漏?

如何避免Java中的内存泄漏&#xff1f; 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 在Java开发中&#xff0c;内存泄漏&#xff08;Memory Leak&#xff0…

CSF视频文件格式转换WMV格式(2024年可用)

如果大家看过一些高校教学讲解视频的话&#xff0c;很可能见过这样一个难得的格式&#xff0c;".csf "&#xff0c;非常漂亮 。 用暴风影音都可以打开观看&#xff0c;会自动下载解码。 但是一旦我们想要利用或者上传视频的时候就麻烦了&#xff0c;一般网站不认这…

STM32重定向printf到串口(重写fputc不生效)

使用STM32开发&#xff0c;想用printf把输出打印到串口&#xff0c;需要重定向printf函数。 网上一搜全都是重写fpuc的&#xff0c;但这只针对使用了MicroLIB的情况&#xff0c;如果你使用STM32CubeMX配置了CMake或者Makefile项目&#xff0c;这种方法是根本不可行的&#xff0…