当前位置: 首页 > news >正文

手写MyBatis第36弹:MyBatis执行流程中SQL命令类型解析

🥂(❁´◡`❁)您的点赞👍➕评论📝➕收藏⭐是作者创作的最大动力🤞

💖📕🎉🔥 支持我:点赞👍+收藏⭐️+留言📝欢迎留言讨论

🔥🔥🔥(源码 + 调试运行 + 问题答疑)

🔥🔥🔥  有兴趣可以联系我。

我们常常在当下感到时间慢,觉得未来遥远,但一旦回头看,时间已经悄然流逝。对于未来,尽管如此,也应该保持一种从容的态度,相信未来仍有许多可能性等待着我们。 

目录

1 SQL命令类型概述与重要性

2 XML配置方式解析SQL命令类型

2.1 解析过程与关键代码

2.2 XML配置示例

3 注解方式解析SQL命令类型

3.1 注解解析过程

3.2 注解配置示例

4 MappedStatement的创建与SQL命令类型的设置

5 SQL命令类型在Executor中的使用

5.1 执行路由决策

5.2 其他影响

6 总结


MyBatis SQL命令类型解析:从注解与XML到MappedStatement的奥秘

  1. 《MyBatis SQL命令类型解析:揭秘@Select/@Insert与XML节点的执行决策依据》

  2. 《深入MyBatis内核:SQL操作类型如何影响Executor的行为路径》

  3. 《手写MyBatis(七):解析SQL命令类型,奠定执行决策基石》

  4. 《从注解/XML到MappedStatement:MyBatis如何确定你的SQL要做什么?》

  5. 《SQL命令类型的奥秘:MyBatis执行流程中的关键枚举值》


MyBatis作为一个优秀的持久层框架,其核心功能之一便是将开发者编写的SQL语句(无论是通过XML还是注解方式)转化为对数据库的实际操作。在这个过程中,准确识别SQL语句的类型(SELECT, INSERT, UPDATE, DELETE)至关重要,因为它直接决定了MyBatis底层执行引擎的行为路径。本文将深入剖析MyBatis如何解析并确定SQL命令类型,并探讨这一信息在后续执行流程中的关键作用。

1 SQL命令类型概述与重要性

在MyBatis中,SqlCommandType是一个枚举类型,它定义了以下几种SQL操作类型:

  • SELECT:对应查询操作,用于从数据库检索数据。

  • INSERT:对应插入操作,用于向数据库插入新数据。

  • UPDATE:对应更新操作,用于更新数据库中的现有数据。

  • DELETE:对应删除操作,用于从数据库中删除数据。

  • (还有其他如FLUSH等较少用的类型)

MappedStatement 对象是 MyBatis 框架的核心类之一,它存储了一个 SQL 对应的所有信息。其 sqlCommandType 属性记录了该 SQL 语句的操作类型。明确记录每条SQL语句的操作类型,是执行时决策(如调用Executor.query还是Executor.update)的依据。

SQL命令类型的重要性主要体现在以下几个方面:

  1. 执行路由决策:MyBatis的Executor会根据sqlCommandType来决定是调用doUpdate方法还是doQuery方法。

  2. 缓存行为控制:例如,SELECT语句通常会查询缓存,而INSERTUPDATEDELETE语句则可能刷新缓存(根据配置)。

  3. 主键生成处理INSERT操作可能需要处理自增主键或序列主键的获取。

  4. 事务语义理解:虽然事务通常由外部管理,但了解操作类型有助于理解数据变更的边界。

2 XML配置方式解析SQL命令类型

当MyBatis解析XML映射文件时,会根据SQL语句所在的XML节点名称来确定其命令类型。

2.1 解析过程与关键代码

MyBatis通过XMLStatementBuilder类来解析XML中的SQL节点。解析过程中,会提取节点的名称,并将其转换为对应的SqlCommandType

 public class XMLStatementBuilder {public void parseStatementNode() {// 获取XML节点的名称,如 "select", "insert", "update", "delete"String nodeName = context.getNode().getNodeName();// 将节点名称转换为大写,并匹配到SqlCommandType枚举值SqlCommandType sqlCommandType = SqlCommandType.valueOf(nodeName.toUpperCase(Locale.ENGLISH));// ... 后续构建MappedStatement时,会使用这个sqlCommandType}}

2.2 XML配置示例

以下是一个XML映射文件的示例,展示了不同类型的SQL语句:

 <mapper namespace="com.example.MyMapper"><select id="selectUser" resultType="User">SELECT * FROM user WHERE id = #{id}</select><insert id="insertUser" parameterType="User" useGeneratedKeys="true" keyProperty="id">INSERT INTO user (name, email) VALUES (#{name}, #{email})</insert><update id="updateUser" parameterType="User">UPDATE user SET name = #{name}, email = #{email} WHERE id = #{id}</update><delete id="deleteUser" parameterType="int">DELETE FROM user WHERE id = #{id}</delete></mapper>

MyBatis在解析上述XML文件时,会根据<select><insert><update><delete>这些节点名称,分别创建SqlCommandTypeSELECTINSERTUPDATEDELETEMappedStatement对象。

3 注解方式解析SQL命令类型

对于使用注解配置的SQL语句,MyBatis通过MapperAnnotationBuilder来解析方法上的注解,并确定其SQL命令类型。

3.1 注解解析过程

MyBatis支持的SQL注解包括@Select@Insert@Update@Delete等。解析器会检查方法上的注解,并根据注解类型来确定SQL命令类型。

 public class MapperAnnotationBuilder {private void parseStatement(Method method) {// 获取方法上的注解Annotation annotation = findAnnotation(method, Select.class, Insert.class, Update.class, Delete.class, ...);SqlCommandType sqlCommandType;if (annotation instanceof Select) {sqlCommandType = SqlCommandType.SELECT;} else if (annotation instanceof Insert) {sqlCommandType = SqlCommandType.INSERT;} else if (annotation instanceof Update) {sqlCommandType = SqlCommandType.UPDATE;} else if (annotation instanceof Delete) {sqlCommandType = SqlCommandType.DELETE;} else {// 处理其他情况或报错}// ... 使用sqlCommandType构建MappedStatement}}

3.2 注解配置示例

public interface UserMapper {@Select("SELECT * FROM users WHERE id = #{id}")User selectUserById(int id);​@Insert("INSERT INTO users (name, email) VALUES (#{name}, #{email})")@Options(useGeneratedKeys = true, keyProperty = "id")int insertUser(User user);​@Update("UPDATE users SET name = #{name}, email = #{email} WHERE id = #{id}")int updateUser(User user);​@Delete("DELETE FROM users WHERE id = #{id}")int deleteUser(int id);}

当MyBatis解析UserMapper接口时,它会读取每个方法上的注解,并根据注解类型(@Select, @Insert, @Update, @Delete)为每个方法对应的MappedStatement设置相应的SqlCommandType

4 MappedStatement的创建与SQL命令类型的设置

无论是通过XML还是注解方式解析,最终都会构建一个MappedStatement对象,其中包含了该SQL语句的所有配置信息,包括sqlCommandType

MappedStatement 对象通过 Builder 模式创建,并在构建过程中设置其属性,包括 sqlCommandType

MappedStatement 的关键属性包括

  • id:通常由命名空间和方法名组成,唯一标识一个MappedStatement。

  • sqlSource:表示解析出来的SQL。

  • sqlCommandType:SQL命令类型(SELECT, INSERT, UPDATE, DELETE等)。

  • parameterType:参数类型。

  • resultType/resultMap:结果类型或结果映射。

  • useCacheflushCache等缓存相关属性。

5 SQL命令类型在Executor中的使用

SQL命令类型(sqlCommandType)信息在Executor的执行方法中被使用,它是决定调用Executorquery方法还是update方法的关键依据。

5.1 执行路由决策

当通过SqlSession调用一个Mapper方法时,MyBatis会找到对应的MappedStatement,并根据其sqlCommandType来决定执行路径:

 public class CachingExecutor implements Executor {@Overridepublic <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {// ... 处理查询操作(SELECT语句)}​@Overridepublic int update(MappedStatement ms, Object parameterObject) throws SQLException {// ... 处理更新操作(INSERT, UPDATE, DELETE语句)}}

DefaultSqlSession中,你可以看到根据sqlCommandType进行路由的逻辑:

public class DefaultSqlSession implements SqlSession {@Overridepublic int insert(String statement, Object parameter) {return update(statement, parameter);}@Overridepublic int update(String statement, Object parameter) {// 对于INSERT, UPDATE, DELETE语句,最终都调用update方法MappedStatement ms = configuration.getMappedStatement(statement);return executor.update(ms, wrapCollection(parameter));}@Overridepublic <E> List<E> selectList(String statement, Object parameter) {// 对于SELECT语句,调用query方法MappedStatement ms = configuration.getMappedStatement(statement);return executor.query(ms, wrapCollection(parameter), RowBounds.DEFAULT, null);}}

值得注意的是,虽然SqlSession提供了insert, update, delete等不同方法,但在MyBatis底层,INSERT, UPDATE, DELETE操作最终都调用Executor.update方法,而SELECT操作则调用Executor.query方法。这是因为从数据库的角度来看,INSERTUPDATEDELETE都是写操作,会改变数据库状态,而SELECT是读操作。

5.2 其他影响

除了决定调用query还是update方法外,sqlCommandType还会影响:

  1. 缓存行为SELECT语句的结果可能会被缓存(根据配置),而写操作通常会刷新缓存。

  2. 事务管理:虽然事务通常由外部管理,但了解操作类型有助于理解数据变更的边界。

  3. 主键生成:对于INSERT语句,MyBatis可能会在处理后获取自增主键值并设置回参数对象。

6 总结

SQL命令类型的解析是MyBatis执行流程中的基础环节,它架起了开发者编写的SQL语句与底层数据库操作之间的桥梁。通过深入了解SqlCommandType的解析过程和作用机制,我们不仅能更好地理解MyBatis的内部工作原理,也能在遇到问题时更快地定位和解决。

无论是XML配置还是注解配置,MyBatis都提供了一致的机制来解析和确定SQL命令类型,并将其封装在MappedStatement对象中。最终,这一信息在Executor的执行方法中被关键性地使用,决定了SQL语句的执行路径和行为,确保了MyBatis能够正确、高效地处理各种数据库操作。


💖学习知识需费心,
📕整理归纳更费神。
🎉源码免费人人喜,
🔥码农福利等你领!

💖常来我家多看看,
📕我是程序员扣棣,
🎉感谢支持常陪伴,
🔥点赞关注别忘记!

💖山高路远坑又深,
📕大军纵横任驰奔,
🎉谁敢横刀立马行?
🔥唯有点赞+关注成!

http://www.xdnf.cn/news/1375075.html

相关文章:

  • 登录业务——密码重置与强制修改初始密码实现思路
  • 【微信小程序】分别解决H5的跨域代理问题 和小程序正常不需要代理问题
  • Coze用户账号设置修改用户名-后端源码
  • map|math
  • 腾讯位置商业授权微信小程序路线规划
  • 【开源工具】基于Flask与Socket.IO的跨平台屏幕监控系统实战(附完整源码)
  • 前端性能优化:从指标监控到全链路落地(2024最新实战指南)
  • 论文阅读:Gorilla: Large Language Model Connected with Massive APIs
  • 深度学习入门:神经网络基础知识
  • lesson47:Linux常用软件使用指南:远程连接、远程拷贝、Vim与Nginx
  • VESA时序检测模块设计verilog实现
  • Ubuntu 24 Server 如何设置无线网络
  • imx6ull-驱动开发篇45——Linux 下 SPI 驱动框架简介
  • d435i相机读取镜头内参和相对之间的外参
  • 艾体宝新闻 | 98%好评率!KnowBe4 连续5年蝉联第一,现开放免费钓鱼测试等你解锁
  • 内网应用如何实现外网访问?外地通过公网地址访问内网服务器的设置方法
  • 遗传算法:模拟自然选择的优化智慧
  • Spring Boot项目集成日志系统使用完整指南
  • 欧洲数字化养殖平台 Herdwatch 借力 Iceberg + StarRocks 提升分析能力
  • 嵌入式开发学习 C++:day01
  • 动态规划:硬币兑换(有趣)
  • LeetCode - 739. 每日温度
  • 线性回归原理推导与应用(十一):多重共线性
  • 获取服务器指标的信息
  • bin log 和 redo log有什么区别
  • Mybatis总结
  • 【如何解决Java中的ClassCastException类转换异常问题】
  • 基于Matlab结合肤色检测与卷积神经网络的人脸识别方法研究
  • 基于MATLAB/Simulink的单机带负荷仿真系统搭建
  • 分布式2PC理论