Mybatis-Generator生成Mapper文件中<if test="criteria.valid">的问题解答
写在前面
由于开源了项目的缘故,很多使用了My Blog项目的朋友遇到问题也都会联系我去解决,有的是把问题留在项目的issue里提出,有的是在我的私人博客里留言,还有的则是直接添加我的qq来找我讲自己遇到的问题,有些问题比较简单直接就解决了,有些问题的解决记录也留在issue记录里,有些则是网上有相关教程,而剩下问题的解决方案,如果时间允许我都会单独的做一篇博客来解答。
问题描述
当时的聊天记录:
截图中提到的代码(节选):
ContentVoMapper.xml:
<sql id="Example_Where_Clause">
<where>
<foreach collection="oredCriteria" item="criteria" separator="or">
<if test="criteria.valid">
<trim prefix="(" prefixOverrides="and" suffix=")">
<foreach collection="criteria.criteria" item="criterion">
<choose>
<when test="criterion.noValue">
and ${criterion.condition}
</when>
<when test="criterion.singleValue">
and ${criterion.condition} #{criterion.value}
</when>
<when test="criterion.betweenValue">
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
</when>
<when test="criterion.listValue">
and ${criterion.condition}
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
#{listItem}
</foreach>
</when>
</choose>
</foreach>
</trim>
</if>
</foreach>
</where>
</sql>
CommentVoExample:
protected abstract static class GeneratedCriteria {
protected List<Criterion> criteria;
protected GeneratedCriteria() {
super();
criteria = new ArrayList<Criterion>();
}
public boolean isValid() {
return criteria.size() > 0;
}
public List<Criterion> getAllCriteria() {
return criteria;
}
public List<Criterion> getCriteria() {
return criteria;
}
...
问题整理:在GeneratedCriteria类中并没有valid这一属性,仅仅只有一个isValid()
方法,但是在Mapper文件中mybatis的<if test>
语法中,却有criteria.valid
的表达式,而且程序可以正常运行,这是怎么回事呢?
思路整理
首先,我刚看到这个问题的时候也是有点懵,因为这个代码其实不是我写的,Mapper文件是我通过Mybatis-Generator自动生成的,所以这段代码我也是有点陌生的,哈哈哈哈。
但是看了一遍代码之后,我觉得应该是mybatis根据valid属性自动找到了isValid()方法,然后执行了逻辑判断,当然,这都是个人感觉,没什么依据,隐隐约约觉得应该是这么个道理。但是呢,毕竟这位朋友是来问问题的,我不能就简简单单的回复这么一句话,而且是连我自己都不确定的答案。
疑惑的问题有:
- 并不知道mybatis是不是这个执行流程;
- 即使是如上的流程,那么为什么根本没有的属性会被mybatis正常解析;
- 为什么mybatis会去执行
isValid()
方法而不去执行其他的方法。
解决过程
带着以上的问题和心中的不确定,我唯一能做的就是去查看这部分过程的源码了,最终也如愿得到了答案,通过IDEA的debug功能得到了代码的执行过程,可以自行执行查看一下整个过程:
- 在
IfSqlNode
类中,获取了if test
标签中表达式的值:criteria.valid
;
- 接着是在
ObjectPropertyAccessor
类中解析到了需要操作的属性值Criteria
类中的valid
;
- 然后是在
OgnlRuntime
类中得到了表达式对应执行的MethodisValid()
方法。
接下来就是执行方法并获取返回值了,就不再截图了。
上面的前两个问题就有了答案:
- 由
<if test="criteria.valid">
到执行isValid()
方法的执行流程找到了,虽然过程较多但是几个重要的节点就是以上三点,获取Mapper表达式中的类名和属性值,然后获取需要执行的方法,最终实现整个功能。 - mybatis并没有去关注是否存在这个属性,而是根据属性去找到对应的方法并执行。
至于第三个问题,我也做了一下扩展,如果其他带有valid字符串的方法会不会也被执行到,结果是肯定回答,如图:
将isValid()
改为getValid()
OgnlRuntime
类中得到了对应执行的MethodgetValid()
方法
当两个方法都存在时,会执行isValid()
方法,因为if test
需要的是一个boolean返回值,当只存在getValid()
方法时,则会执行getValid()
。
结语
首发于我的个人博客。
如果有问题或者有一些好的创意,欢迎给我留言,也感谢向我指出项目中存在问题的朋友,关于这篇文章,特别感谢一下@libinghui
。
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- python实现PDF中表格转化为Excel的方法
- php实现算术验证码功能
- 基于matplotlib中ion()和ioff()的使用详解
- Laravel5.7框架安装与使用学习笔记图文详解
- Python基于httpx模块实现发送请求
- Python Tkinter图形工具使用方法及实例解析
- PHP实现的简单留言板功能示例【基于thinkPHP框架】
- Python SMTP配置参数并发送邮件
- Python如何实现自带HTTP文件传输服务
- 在keras中实现查看其训练loss值
- keras实现VGG16方式(预测一张图片)
- 利用python中的matplotlib打印混淆矩阵实例
- pytorch加载自己的图像数据集实例
- python实现批量转换图片为黑白
- Keras构建神经网络踩坑(解决model.predict预测值全为0.0的问题)