概述

在业务中如果dao层搭配了mybatis,那么通常会将一些业务查询写入到xml中,并且在过滤一些业务条件时会使用OGNL表达式

比如下面这段OGNL表达式

<if test="null != params.applyTimeStart">
    and mpa.apply_time >= #{params.applyTimeStart}
</if>

<if test="null != params.applyTimeEnd">
    and mpa.apply_time &lt;= #{params.applyTimeEnd}
</if>

可以看到在表达式中是通过xxx.xxx的方式取值的;
先说结论,通过get方法获取的值

org.apache.ibatis.reflection.Reflector#getGetInvoker
在这里插入图片描述

mybatis:3.5.10

源码分析

思路大致是先从外层查询进去,然后一路debug进去;

我的查询入口是个分页查询,我在中间源码setParameters处打了个断点
com.baomidou.mybatisplus.core.MybatisParameterHandler#setParameters

然后一路往下跟踪到BeanWrapper中的metaClass.getGetInvoker方法,在其中看到了查询get方法的逻辑
org.apache.ibatis.reflection.wrapper.BeanWrapper#getBeanProperty
在这里插入图片描述

获取get方法的逻辑
org.apache.ibatis.reflection.Reflector#getGetInvoker
在这里插入图片描述

OGNL的比较优先级源码分析

OGNL中进行比较时会自动进行类型转换,类型转成一直后才会进行比较;

先说顺序结论

  1. 如果是同一类型 → 直接比较
  2. 如果都是 Number → 数值比较
  3. 如果可以转换为 Number → 转换为 Number 比较
  4. 否则 → 使用 equals()

在业务中有时会需要传入动态比较符号进行比较;

下面是一个有问题的判断方式;
问题在于其中的 <when test="'=' == compareCondition">进行num转换时会报错;
前面是char后面是string,此时mybatisognl会先进行类型比较转换;发现类型不一致,并且不是num,会尝试转成num;

比较入口
org.apache.ibatis.ognl.ASTEq#getValueBody
在这里插入图片描述

具体类型转换比较
org.apache.ibatis.ognl.OgnlOps#isEqual
在这里插入图片描述

<choose>
    <when test="'&amp;gt;' == compareCondition">
        >
    </when>
    <when test="'&amp;gt;=' == compareCondition">
        >=
    </when>
    <when test="'&amp;lt;' == compareCondition">
        &lt;
    </when>
    <when test="'&amp;lt;=' == compareCondition">
        &lt;=
    </when>
    <when test="'=' == compareCondition">
        =
    </when>
</choose>
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐