写在前面

《Docker+SpringBoot+Mybatis+thymeleaf的Java博客系统开源啦》

由于开源了项目的缘故,很多使用了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

代码和这次的问题都是My Blog项目中的,如果你想继续了解该项目可以查看整个系列文章Java开源博客My-Blog(SpringBoot+Docker)系列文章,也可以到我的GitHub仓库或者开源中国代码仓库中查看源码及详细的部署过程和使用文档。

Mybatis-Generator生成Mapper文件中<if test="criteria.valid">的问题解答的更多相关文章

  1. Mybatis逆向生成Mapper文件

    本文参考博客 http://blog.csdn.net/for_my_life/article/details/51228098 1. 在resources根目录下添加generator.proper ...

  2. Mybatis 自动生成mapper文件

    在pom.xml下的<build>内加入: <build> <plugins> <plugin> <groupId>org.mybatis. ...

  3. Maven下用MyBatis Generator生成文件

    使用Maven命令用MyBatis Generator生成MyBatis的文件步骤如下: 1.在mop文件内添加plugin <build> <finalName>KenShr ...

  4. MyBatis mapper文件中的变量引用方式#{}与${}的差别

    MyBatis mapper文件中的变量引用方式#{}与${}的差别 #{},和 ${}传参的区别如下:使用#传入参数是,sql语句解析是会加上"",当成字符串来解析,这样相比于$ ...

  5. ][mybatis]MyBatis mapper文件中的变量引用方式#{}与${}的差别

    转自https://blog.csdn.net/szwangdf/article/details/26714603 MyBatis mapper文件中的变量引用方式#{}与${}的差别 默认情况下,使 ...

  6. MyBatis mapper文件中使用常量

    MyBatis mapper文件中使用常量 Java 开发中会经常写一些静态常量和静态方法,但是我们在写sql语句的时候会经常用到判断是否等于 //静态类 public class CommonCod ...

  7. mybatis Generator生成代码及使用方式

    本文原创,转载请注明:http://www.cnblogs.com/fengzheng/p/5889312.html 为什么要有mybatis mybatis 是一个 Java 的 ORM 框架,OR ...

  8. mybatis逆向工程生成mapper报错

    Result Maps collection already contains value for xxxMapper.BaseResultMap错误解决办法一.问题描述今天在做项目时,遇到一个错误: ...

  9. 使用mybatis-generator插件结合tk.mybatis自动生成mapper二三事

    本篇文章将介绍使用spring boot框架,引入mybatis-generator插件,结合tk.mybatis自动生成Mapper和Entity的一整套流程,其中包括最重要的踩坑与填坑.     ...

随机推荐

  1. R语言统计分析技术研究——卡方检验的思想和实现

    卡方检验的思想和实现 作者:李雪丽 材料摘自:百度

  2. jsp图片上传

    1.要实现图片上传,首先需要一个组件,这里我用的是smartupload.jar可以到这里下载http://download.csdn.net/detail/mengdecike/8279247 2. ...

  3. 如何将mysql数据导入Hadoop之Sqoop安装

    Sqoop是一款开源的工具,主要用于在Hadoop(Hive)与传统的数据库(mysql.postgresql...)间进行数据的传递,可以将一个关系型数据库(例如 : MySQL ,Oracle , ...

  4. jquery 检测某元素是否含有某属性

    检测某元素是否含有某属性 if(typeof($("#aid").attr("rel"))=="undefined")

  5. PHP中小小的header函数

    不废话,直接说功能 1.重定向,语法: header("location:http://www.lemon-x.ga"); file_put_contents("./te ...

  6. JavaScript深入浅出补充——(一)数据类型,表达式和运算符

    项目基本做完,在进行下一阶段学习之前先看视频学习回顾一下JavaScript 一.数据类型 JavaScript中有五种原始类型和一种对象类型 JavaScript弱类型语言中隐式转换 num-0 字 ...

  7. MyEclipse 2014 破解补丁及激活步骤

    针对 MyEclipse Trail Expired 问题的解决方法 我用网上找的注册类生成注册码的方式注册了一下,重启MyEclipse仍然会有提示弹窗,不过剩余时间由 4 days变成了 5 da ...

  8. 用CSS3实现无限循环的无缝滚动

    有时候在页面的某个模块中,需要无限循环的滚动一些消息.那么如果我们用js实现无缝衔接滚动的思路是什么呢(比如我们这个模块是向上滚动的)? 克隆A一份完全一样的数据B放在原数据A的后面: 使用setIn ...

  9. Docker 的两类存储资源 - 每天5分钟玩转 Docker 容器技术(38)

    我们从本章开始讨论 Docker 存储. Docker 为容器提供了两种存放数据的资源: 由 storage driver 管理的镜像层和容器层. Data Volume. 我们会详细讨论它们的原理和 ...

  10. Tomcat管理页面配置

    详情参考:http://www.365mini.com/page/tomcat-manager-user-configuration.htm 修改$CATALINA_BASE/conf/tomcat- ...