八、动态SQL解析原理MyBatis的动态SQL是通过OGNL表达式来实现的 。OGNL(Object-Graph Navigation Language)是一种基于Java对象图遍历的表达式语言,它可以方便地访问Java对象的属性和方法 。
在MyBatis中,通过OGNL表达式可以动态地计算条件是否成立,从而确定是否将SQL片段添加到最终的SQL语句中 。OGNL表达式通常嵌入在MyBatis中的动态SQL标签中,例如if、choose、when、otherwise等 。
MyBatis使用了两个重要的类来实现OGNL表达式的解析和计算:OgnlExpressionEvaluator和OgnlCache 。OgnlExpressionEvaluator类负责将MyBatis传入的参数对象转换为OGNL表达式需要的上下文对象,然后将OGNL表达式计算结果返回;OgnlCache类负责缓存已经解析好的OGNL表达式,避免重复解析和计算 。
具体的解析过程如下:
- 根据MyBatis的配置将MApper.xml文件中的SQL语句解析为一个MappedStatement对象,并将其中的OGNL表达式解析成一个一个可执行的SQL片段 。
- 对于每一个OGNL表达式,MyBatis使用${}来表示一个简单的OGNL表达式,使用#{}来表示一个OGNL表达式中包含复杂逻辑的情况 。在解析过程中,MyBatis会将OGNL表达式中的参数进行解析和预处理,然后使用OgnlCache类将其缓存起来 。
- 当Mapper接口方法被调用时,MyBatis会将方法中传入的参数对象转换为一个BoundSql对象,并将该BoundSql对象与MappedStatement对象一起传递给OgnlExpressionEvaluator类 。
- OgnlExpressionEvaluator类中再次解析OGNL表达式,并将BoundSql对象作为上下文传入OGNL表达式中执行 。OGNL表达式执行的结果将被转化为String类型,并返回给BoundSql对象 。
- 最后,MyBatis将所有BoundSql对象中的SQL片段拼接成最终的SQL语句并执行 。
在 MyBatis 的源码中,动态 SQL 还涉及到以下接口和类来实现:
- SqlNode 接口:表示一个 SQL 节点,也就是一个 SQL 片段 。它包含一个 apply 方法,在执行 SQL 语句时会将 SQL 片段应用到相应的位置 。
- MixedSqlNode 类:实现了 SqlNode 接口,可以包含多个子节点 。该类的 apply 方法会依次遍历所有子节点,并将每个节点应用到 SQL 语句中 。
- TextSqlNode 类:表示一个纯文本节点 。该类包含一个文本字符串,可以将其直接应用到 SQL 语句中 。
- IfSqlNode 类:表示一个条件节点 。可以根据指定的条件判断是否需要应用该节点内部的 SQL 片段 。如果条件成立,则会将 SQL 片段应用到 SQL 语句中 。
- TrimSqlNode 类:表示一个修剪节点,可以根据配置对 SQL 片段进行修剪操作 。常用于处理 UPDATE 和 INSERT 语句中 SET 子句的逗号问题 。
- WhereSqlNode 类:表示一个 WHERE 条件节点 。可以将 WHERE 子句的参数拼接到 SQL 语句中 。
文章插图
以上是 MyBatis 中实现动态 SQL 的核心接口和类 。MyBatis 内部通过组合这些接口和类来构建复杂的 SQL 语句 。通过定义这些接口和类,可以让开发者更加方便地书写动态 SQL 语句,并且遵循了设计模式中的单一职责原则 。
还有一些Builder 接口及其实现类的作用都是用于构造 SQL 语句 。下面简单介绍一下一些常用的 Builder 类型:
- BaseBuilder 接口:所有 Builder 的基础接口,定义了一些共同的方法,例如获取 Configuration 对象、创建 ParameterMapping 对象等 。
- XMLMapperBuilder 类:从 XML 文件中解析出各种 SQL 节点,然后通过其他 Builder 对象将其转换成 SQL 语句 。
- MapperBuilderAssistant 类:辅助 XMLMapperBuilder 类创建各种类型的 SQL 节点,例如创建 <select>、<update>、<insert> 等标签节点 。
- SqlSourceBuilder 类:根据 XML 中的 SQL 片段创建 SqlSource 对象,SqlSource 对象中包含了解析后的 SQL 语句和参数信息 。
- DynamicSqlSource 类:用于处理动态 SQL,也就是包含各种条件判断和循环语句的 SQL 片段 。它是 SqlSource 接口的一种实现 。
- StaticSqlSource 类:用于处理静态 SQL,即不包含任何条件语句和循环语句的 SQL 片段 。它同样是 SqlSource 接口的一种实现 。
推荐阅读
- 王思佳|Selina同学、杨祐宁初恋?深陷假包风波的王思佳故事不简单
- |夜钓黄鸭叫,就用这2种钓法,连竿上鱼很简单
- 短发|尝试一下齐颈发,洋气减龄,谁剪谁美
- 宝石|老宝石类文玩为啥贵?还真没那么简单!
- |打破悬坠调漂,一直似懂非懂的魔咒,简单调漂后,一劳永逸
- 从简单到复杂,密码学让我们的信息更安全
- 超简单的Kafka架构入门指南,看这一篇就够了
- 黄蓉|“最丑黄蓉”出炉!徐克翻拍《射雕》,女主遭吐槽被扒身份不简单
- 求职|现在的就业确实很难。但大学生找工作一定是最简单的。
- 贵州|贵州80后美女官员被查,长期在同一部门任职,背后靠山不简单