国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > Java > 正文

解析Mybatis判斷表達式源碼分析

2024-07-14 08:42:32
字體:
來源:轉載
供稿:網友

在我們開發過程中用 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 的所對應的值,如下所示

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!=nullNode[1] : array != ''

然后這里面的兩個參數 v1 和 v2 分別為左邊和右邊的參數,此時先解析 Node[0] 中的參數

  • v1 :就是參數 array 對應的數組的值
  • v2 :就是null

此時到這應該就知道為什么 String 數組為什么能和空字符串進行比較了,因為他將數組轉化為了 Object 然后用自己寫的 equal 方法進行比較。然后進去他寫的 equal 方法中看了以后發現他對數組比較是特殊的。

  • 如果左邊是數組右邊是字符串:兩個都轉換為 Object 然后進行 v1.getClass()==v2.getClass() 判斷
  • 如果左邊是數組右邊也是數組:先判斷兩個數組的長度是否相同,如果相同,那么循環遍歷兩個數組進行里面的值的比較

總結

以上所述是小編給大家介紹的解析Mybatis判斷表達式源碼分析,希望對大家有所幫助,如果大家有任何歡迎給我留言,小編會及時回復大家的!


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 修水县| 马公市| 广丰县| 芒康县| 涞水县| 布尔津县| 温宿县| 澳门| 保亭| 凌云县| 加查县| 福州市| 渭南市| 新建县| 随州市| 宜兰县| 天峨县| 鄂托克前旗| 法库县| 岳阳县| 高雄市| 虎林市| 大安市| 漠河县| 会昌县| 乌审旗| 井陉县| 鹿泉市| 丰原市| 辉南县| 石家庄市| 云阳县| 云南省| 南华县| 六盘水市| 武陟县| 聂拉木县| 吴江市| 阜新市| 肇州县| 通海县|