sql字符串拼接_Mybatis的SqlSession执行sql过程
上一篇分析了SqlSession執行sql的過程,其中并沒有分析sql是從哪里來的,今天就來仔細分析下。
Sql來源
從上一篇的最后一步執行sql那里倒推sql的來源,源碼主要過程如下圖:
可以看到最后是通過BoundSql直接獲取的sql,然后往前倒推最后發現是通過MappedStatement的getBoundSql方法返回的。MappedStatement在之前分析mapper的時候知道一個執行sql對應一個MappedStatement對象,它封裝有mybatis中需要執行一條sql的所有信息,所以從這里獲取也是理所應當的。
MappedStatement的getBoundSql方法
那么就來看下MappedStatement的getBoundSql方法吧,源碼如下圖:
首先是右邊MappedStatement的getBoundSql方法,這次改了下sql傳遞了兩個參數,但是對程序基本沒什么影響。可以看到BoundSql是通過SqlSource創建的,通過debug知道是DynamicSqlSource對象。
左邊是DynamicSqlSource的getBoundSql方法,可以先看后面的創建BoundSql對象,是通過SqlSource初始化的,而創建SqlSource對象需要的第一個參數是通過context.getSql()得到的。
而在getBoundSql方法第一步是初始化了context,從上圖的debug可以看到目前context的信息,bindings屬性已經通過初始化把參數設置進去,而sqlBuilder還是一個空字符串。關鍵代碼就在當前打斷點的“rootSqlNode.apply(context);”這行代碼。
從上圖可以看到rootSqlNode是一個MixedSqlNode對象,MixedSqlNode對象的apply方法是遍歷屬性contents的所有元素并執行它們的apply方法,可以看到contents只有一個TextSqlNode對象的元素。所以最終來到TextSqlNode對象。
TextSqlNode對象的text屬性保存的就是還沒有進行處理的sql。
TextSqlNode處理sql
TextSqlNode處理sql的源碼如下圖:
右側是TextSqlNode的apply方法,參數context就是上一步需要的context,他里面包含有請求參數,從上一張源碼圖可以知道它的屬性sqlBuilder此時還是一個空字符串,而apply就是去拼接sqlBuilder。
apply方法首先創建了一個GenericTokenParser對象,GenericTokenParser對象有三個屬性openToken、closeToken、handler。其中openToken、closeToken分別對應字符串”${”、”}”,而handler的屬性context對應傳遞進來的context,injectionFilter屬性是TextSqlNode的injectionFilter。apply第二行代碼“context.appendSql(parser.parse(text));”可以看出來parser.parse(text)就是生成sql的代碼。其中text是TextSqlNode中沒有處理的原始sql。
所以sql生成在GenericTokenParser的parse方法,parse方法的關鍵源碼如上圖左側。主要步驟分析如下:
1、從sql找到第一個“${”位置start,獲取到元素sql(text)的字符數組src;
2、把src從開始到start處的字符拼接到結果builder上,也就是把“${”的內容拼接到結果上;
3、從start+2的位置開始找“}”的位置end,從src數組里取出“${”、“}”之間的字符組成字符串并根據字符串從hander中取出字符串對應的參數值。并把值拼接到結果builder上。
最后還有一點代碼沒有截取到“start = text.indexOf(openToken, offset);
} while (start > -1);”也就是第4步。
4、繼續找到下一個“${”并拼接。最終組成完整的sql。
實際上GenericTokenParser的parse方法還是比較簡單的,就是把傳遞進來的參數text中openToken、closeToken中間的內容替換成對應的參數。
總結
從之前的分析我們知道一個MappedStatement對應一個sql,那么如何從MappedStatement獲取組裝好的sql呢,實際上是MappedStatement的屬性sqlSource。
而sqlSource實際上是依靠rootSqlNode,在之前我們分析過解析mapper文件是把sql生成了嵌套的各種SqlNode子類。今天就看到他們的使用了。不過今天的算是比較簡單的,后面來一個稍微復雜一點的看看sql的解析過程。
Java程序員日常學習筆記,如理解有誤歡迎各位交流討論!
總結
以上是生活随笔為你收集整理的sql字符串拼接_Mybatis的SqlSession执行sql过程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Intel处理器明年又要换LGA1851
- 下一篇: wince2秒快速启动TOC分析