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

【十五】Mybatis动态SQL实现原理

Mybatis动态SQL实现原理

目录

Mybatis动态SQL实现原理

概述

动态 SQL

实现原理

总结


概述

        每天日常开发都在使用mybatis,但是很多人并没有花心思去理解mybatis的实现原理,一直处于使用阶段,程序员的使命是改变世界,这一点可能很多人没有在意,但是在意的人的确在意了,所以一直在努力。

动态 SQL

        大家应该日常都在使用这一特性,下面是我从官网找的一个例子:

<select id="findActiveBlogLike"resultType="Blog">SELECT * FROM BLOG<where><if test="state != null">state = #{state}</if><if test="title != null">AND title like #{title}</if><if test="author != null and author.name != null">AND author_name like #{author.name}</if></where>
</select>

这里使用了<select> 、<if>、<where> 这些标签,我们在实际工作中还会使用其他的标签,到这里大家应该是比较熟悉的,接下来我将讲解一下这些标签的实现原理。

实现原理

        Mybatis中可以通过注解(@Select、@Insert、@Delete、@Update)和xml配置文件这两种方式配置sql信息,如果我们要实现这样一个功能,我们该怎么做呢?

        首先,我们是不是需要设计一个类来接受sql解析的信息,这里mybatis设计了SqlSource:

可以看到,这里有四个不同的实现,分别有不同的作用,这些细节大家可以翻阅源码阅读,中间的实现细节这里略过,重点讲解一下sql配置信息到sqlSource对象的转换过程。

这里我们需要了解一个核心实现LanguageDriver:

这里我们重点关注XMLLanguageDriver和RawLanguageDriver实现,XMLLanguageDriver支持XML标签实现动态SQL的功能,RawLanguageDriver支持静态SQL配置功能。

XMLLanguageDriver实现了父类LanguageDriver接口中两个重载的方法分别用来处理xml方式和Java注解方式配置的sql信息。在处理xml配置文件中我们可以看到是通过XMLScriptBuilder类的parseScriptNode()方法实现的,在这个类里我们看到了如下标签:

private void initNodeHandlerMap() {nodeHandlerMap.put("trim", new TrimHandler());nodeHandlerMap.put("where", new WhereHandler());nodeHandlerMap.put("set", new SetHandler());nodeHandlerMap.put("foreach", new ForEachHandler());nodeHandlerMap.put("if", new IfHandler());nodeHandlerMap.put("choose", new ChooseHandler());nodeHandlerMap.put("when", new IfHandler());nodeHandlerMap.put("otherwise", new OtherwiseHandler());nodeHandlerMap.put("bind", new BindHandler());}

分析到这里感觉实现好清晰,如果我们自己来设计估计也是这样的方式吧。这里有个惊喜就是注解方式实际上也是通过XMLScriptBuilder类解析的,这里需要注意的是在注解中要加入<Script>标签,这里注解里面的内容解析处理也是XNode对象。

总结

        闲来无事大概分析了一下Mybatis动态SQL实现原理,很多细节没有去讲解,因为这里面内容很简单而且资料多如牛毛,不愿再做过多重复阐述,写这篇文章只是对自己的理解进行一次梳理,以便温故知新!

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

相关文章:

  • 【Vue】全局事件总线 TodoList 事件总线
  • UE5 MetaHuman眼睛变黑
  • Kafka的Log Compaction原理是什么?
  • Kafka Consumer的auto.offset.reset参数有哪些配置?适用场景?
  • 关系型数据库与非关系型数据库深度对比:从设计哲学到应用场景的全解析
  • 前端取经路——JavaScript修炼:悟空的九大心法
  • 【从零开始学习RabbitMQ | 第二篇】生成交换机到MQ的可靠性保障
  • 原生 IP(Native IP)
  • js获取uniapp获取webview内容高度
  • 【中间件】brpc之工作窃取队列
  • 车载通信网络安全:挑战与解决方案
  • 小微企业SaaS ERP管理系统,SpringBoot+Vue+ElementUI+UniAPP
  • PDF扫描件交叉合并工具
  • 【背包dp----01背包】例题1------[NOIP2001]装箱问题(简化的01背包)
  • Sublime PrettyJson 快捷键
  • 在 Laravel 12 中实现 WebSocket 通信时进行身份验证
  • ts bug 找不到模块或相应类型的声明,@符有红色波浪线
  • Prometheus实战教程:k8s平台-使用文件服务发现案例
  • Android Retrofit框架分析(三):自动切换回主线程;bulid的过程;create方法+ServiceMethod源码了解
  • 【Azure Redis 缓存】关于Azure Cache for Redis 服务在传输和存储键值对(Key/Value)的加密问题
  • Windows系统修改Docker Desktop(WSL2)内存分配
  • Facebook隐私保护措施的优缺点解析
  • Java面试全栈解析:Spring Boot、Kafka与Redis实战揭秘
  • Jenkins+Newman实现接口自动化测试
  • 蓝桥杯-通电(最小生成树java)
  • Axure : 列表分页、 列表翻页
  • 第1.3讲、什么是 Attention?——从点菜说起 [特殊字符]️
  • FastJSON 使用 `Feature.OrderedField` 修复 `JSONObject` 序列化字段顺序问题
  • 用 GRPO 魔法点亮Text2SQL 的推理之路:让模型“思考”得更像人类
  • AI服务器的作用都有哪些?