MyBatis 源碼分析——動態SQL語句


有幾年開發經驗的程序員應該都有暗罵過原生的SQL語句吧。因為他們不能一句就搞定一個業務,往往還要通過代碼來拼接相關的SQL語句。相信大家會理解SQL里面的永真(1=1),永假(1=2)的意義吧。所以mybatis動態SQL功能在筆者看來是最引吸人的。為了更好的區別XML映射文件上的SQL語句。mybatis把SQL語句分為四類。那么這個筆者已經在前面的章節里面講過了。但是我們在開發過程中常常用到的也就倆種:靜態和動態。

關於靜態和動態的定義,筆者是這樣子理解的——靜態SQL語句顯示就是里面沒有相關的羅輯。即是沒有#if之類的語活。反之則是動態SQL語句。而筆者感興趣是動態SQL部分。我們都知道在讀取XML映射文件信息的時候就會分析當前的SQL語句屬於哪一種類型。這部分工作就是放在源碼的XMLScriptBuilder類里面。

 1  public SqlSource parseScriptNode() {
 2     List<SqlNode> contents = parseDynamicTags(context);
 3     MixedSqlNode rootSqlNode = new MixedSqlNode(contents);
 4     SqlSource sqlSource = null;
 5     if (isDynamic) {
 6       sqlSource = new DynamicSqlSource(configuration, rootSqlNode);
 7     } else {
 8       sqlSource = new RawSqlSource(configuration, rootSqlNode, parameterType);
 9     }
10     return sqlSource;
11   }

看到了吧,是通過成員isDynamic的值來獲取相關類型的SQL語句類。DynamicSqlSource類從字面上來講就很容易看出來是屬於動態的。而下面便是靜態的。關鍵的部分還是在parseDynamicTags方法里面。

為了實現動態SQL語句的功能。mybatis設置幾個動態的節點。如if,choose 等。當然如果你們想要知道有幾個的話,最好跟筆者一樣子點開他相關的DTD文件。如下

<!ELEMENT select (#PCDATA | include | trim | where | set | foreach | choose | if | bind)*>

我們可以看到include 、trim 、where 、set 、foreach 、choose 、if 、bind。各自的用法在官網上面有些詳細的說明。 大家可以去看看。相信大家看到這里心里應該有了一定的想法。為了實現動態SQL,那么mybatis一定會根據不同的節點來做不同的邏輯處理。這也是筆者為什么說——關鍵的部分還是在parseDynamicTags方法里面。因為parseDynamicTags方法是用於分析當前select或是delete等節點的SQL節點(即是SqlNode類)。可以說終於生成的SQL語句就是靠這若干個SqlNode類提供生成的。在前面幾章中我們有講到關於BoundSql類的作用。在這里就一下明白了。如下圖

通過parseDynamicTags方法分析出需要用到的若干個SqlNode類。並確定他是否是動態SQL語句。如果是,就創建DynamicSqlSource類。而DynamicSqlSource類會存放在MappedStatement類里面。當我們要通過BoundSql類來生成StatementHandler實例的時候,就會從通過MappedStatement類獲得對應的BoundSql類。而BoundSql類的getSql方法就會我們最終的落點。

其實筆者的內心是有一點小失望的。我本以為mybatis會一直實現自己的元素處理。當然這只是筆者內心的一點完美主義吧。正如官網上講的MyBatis 采用功能強大的基於 OGNL 的表達式來消除其他元素。所以我們可以源碼里面看到ognl的應用。

 Map<Object, OgnlClassResolver> context = Ognl.createDefaultContext(root, new OgnlClassResolver());

對於ongl筆者就不想多說了。有興趣的讀者們可以自己去看一下。筆者建議還是去看一下吧。struts2框架里面也用到他了。

關於mybatis系列筆者就記錄到這里了。希望對大家有用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM