不学无数——Mybatis解析判断表达式源码分析

栏目: Java · 发布时间: 6年前

内容简介:在我们开发过程中用Mapper如下XMl中的sql如下

Mybatis解析判断表达式源码分析

在我们开发过程中用 Mybatis 经常会用到下面的例子

Mapper如下

Map<String ,String > testArray(@Param("array") String [] array);

XMl中的 sql 如下

<select id="testArray" resultType="map">
    select * from t_ams_ac_pmt_dtl where  cpt_pro=#{cptProp}
    <if test="array!=null and array != '' ">
        and cpt_pro=#{cptProp}
    </if>
</select>

刚看上面的代码会觉得数组怎么能和空字符串进行一起比较呢,一开始会觉得这个代码运行起来绝对报错,但是写单元测试运行了一遍发现成功运行了。因此想是不是 Mybatis 在内部对数组类型的数据进行了封装。于是有了这一次的源码解析之旅。上网查了查发现  Mybatis 解析使用了  OGNL 。至于什么是  OGNL 摘抄了百度百科中的一段话

OGNL是Object-Graph Navigation Language的缩写,它是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用相同的表达式去存取对象的属性。这样可以更好的取得数据。

单元测试类如下

@Test
    public void testArray(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        TBapCheckPtsTranscdMapper mapper = sqlSession.getMapper(TBapCheckPtsTranscdMapper.class);
        String str= "1,2,3";
        String [] strings = str.split(",");
        mapper.testArray(strings);
    }

首先我们先来看一下 DynamicSqlSource 这个类,这个类中有个方法如下

@Override
  public BoundSql getBoundSql(Object parameterObject) {
    DynamicContext context = new DynamicContext(configuration, parameterObject);
    rootSqlNode.apply(context);
    SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
    Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass();
    SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType, context.getBindings());
    BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
    for (Map.Entry<String, Object> entry : context.getBindings().entrySet()) {
      boundSql.setAdditionalParameter(entry.getKey(), entry.getValue());
    }
    return boundSql;
  }

其中

rootSqlNode.apply(context);

这段代码对SQL进行了动态的拼接,然后点进去看一下

@Override
  public boolean apply(DynamicContext context) {
    for (SqlNode sqlNode : contents) {
      sqlNode.apply(context);
    }
    return true;
  }

这里的SQL拼接运用了 组合模式 不同的  sqlNode 调用的方法不一样,但是最后的想要结果都是一样的:拼接SQL。例如我们第一次进  apply 这个方法中的时候他跳转到了

StaticTextSqlNode 这个类中调用了下面的方法

@Override
  public boolean apply(DynamicContext context) {
    context.appendSql(text);
    return true;
  }

直接将SQL拼接为

select * from t_ams_ac_pmt_dtl where  cpt_pro=#{cptProp}

然后我们第二次循环执行发现它跳转到了 IfSqlNode 这个类中,这是标签为  <if> 的判断类,

@Override
  public boolean apply(DynamicContext context) {
    if (evaluator.evaluateBoolean(test, context.getBindings())) {
      contents.apply(context);
      return true;
    }
    return false;
  }

在解析语句中传了两个参数进去

evaluator.evaluateBoolean(test, context.getBindings())
  • test  :就是要解析的表达式,在此场景下就是  array!=null and array != ''
  • context.getBindings()  :获得的是一个Map,其中存储了参数  array  的所对应的值,如下所示

不学无数——Mybatis解析判断表达式源码分析

image

然后接下来就到了 OGNL 解析表达式了,发现最后到了  ASTNotEq 这类中

protected Object getValueBody(OgnlContext context, Object source) throws OgnlException {
        Object v1 = this._children[0].getValue(context, source);
        Object v2 = this._children[1].getValue(context, source);
        return OgnlOps.equal(v1, v2) ? Boolean.FALSE : Boolean.TRUE;
    }

这里解析分为了两步进行解析,上面的表达式为 array!=null and array != '' 那么他会根据and 进行分组将其放入  Node 数组中。

  • Node[0]  :  array!=null
  • Node[1]  :  array != ''

然后这里面的两个参数 v1 和  v2 分别为左边和右边的参数,此时先解析  Node[0] 中的参数

  • v1  :就是参数  array  对应的数组的值
  • v2  :就是null

此时到这应该就知道为什么 String 数组为什么能和空字符串进行比较了,因为他将数组转化为了  Object 然后用自己写的  equal 方法进行比较。然后进去他写的  equal 方法中看了以后发现他对数组比较是特殊的。

  • 如果左边是数组右边是字符串:两个都转换为  Object  然后进行  v1.getClass()==v2.getClass()  判断
  • 如果左边是数组右边也是数组:先判断两个数组的长度是否相同,如果相同,那么循环遍历两个数组进行里面的值的比较

以上所述就是小编给大家介绍的《不学无数——Mybatis解析判断表达式源码分析》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Open Data Structures

Open Data Structures

Pat Morin / AU Press / 2013-6 / USD 29.66

Offered as an introduction to the field of data structures and algorithms, Open Data Structures covers the implementation and analysis of data structures for sequences (lists), queues, priority queues......一起来看看 《Open Data Structures》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具