1. 程式人生 > >MyBatis源碼解析【6】SqlSession運行

MyBatis源碼解析【6】SqlSession運行

eight 只需要 dem ctrl+ ssi left 定義 快捷鍵 null

前言

這個分類比較連續,如果這裏看不懂,或者第一次看,請回顧之前的博客

http://www.cnblogs.com/linkstar/category/1027239.html

經過之前的學習我們知道了工廠是如何建立的,是如何生產產品的。

那麽今天要進入重點中的重點了。那就是我們究竟是如何使用這個產品的。

也就是SqlSeesion究竟是如何運行的,內部究竟有些什麽東西。

這部分很難,需要使用到我們之前的基礎裝備哦。

產品運行的大致步驟

我們還是老規矩從外部來看看是如何運行的。

SqlSession session = sqlSessionFactory.openSession();

Demo demo = (Demo) session.selectOne("com.xex.dao.mapper.DemoMapper.selectDemo");session.close();從外部看,最簡單的情況就是這樣,看起來比較簡單。1、從工廠獲取產品(獲取產品已經在上節提到,這裏就不多說了)2、執行需要的sql方法(重點)3、關閉產品(回收產品)

產品運行的內部過程

從大致的步驟我們可以看出重點就在第二步上面了。怎麽隨便調用一個方法就能執行sql了呢?過程復雜,我盡量講的仔細一些。我們就以這個查詢來作為例子。 首先我們進入selectOne方法裏面看看。(idea使用快捷鍵Ctrl+Alt+B查看光標上的方法的實現)

技術分享

我們需要查看的是DefaultSqlSession的實現,至於為什麽之前已經講過咯。

技術分享

留意一個地方,我們傳入的參數statement="com.xex.dao.mapper.DemoMapper.selectDemo"

技術分享

從大方向上看,傳入的參數是“com.xex.dao.mapper.DemoMapper.selectDemo”,返回的參數是一個類MappedStatement

技術分享

mappedStatements簡述

這裏用文字來敘述一下這個mappedStatements的構建思路。因為具體細節太多,就不一一截圖說明了,就截圖重點部分了,希望你能跟上並按照思路去源碼中尋找。

但是這個類裏面一些細節值得我們學習和研究,所以很值得看看。

1、首先這mappedStatements是我們熟悉的Configuration類中的一個變量。

2、是這樣被new出來的:new StrictMap

3、StrictMap是Configuration中的一個內部類繼承自HashMap,與之不同的是的,這個map有個名字name的變量,然後主要不同在於這個map的put和get方法。

4、put方法中:

技術分享

下面有這麽幾句話是用來描述這個put方法的,看完之後仔細思考,這三條是怎麽總結出來的。

一、這個map會把com.xex.dao.mapper.DemoMapper.selectDemo這種包名按照“.”拆分後取出最後一個元素,這裏就是selectDemo。(只是舉例)

二、這個map的值都是String,如果在put的時候發現有相同的key,那麽不會馬上拋出異常,而是覆蓋了重復的鍵,把重復鍵的值修改成了Ambiguity類型。

三、Ambiguity這個類其實就是一個字符串。

首先對於第一條,因為拆分之後最後的selectDemo是我們寫的一條條sql語句的id,mybatis是通過這個id去尋找需要運行那一條數據庫語句的,所以這個必須唯一。而存放的時候只需要最後的selectDemo就可以了。

那麽就奇怪了,為什麽mybatis遇到相同的鍵也就是有兩條sql語句有相同的id時沒有直接選擇在加載配置的時候就拋出異常而是存放了一個奇怪的Ambiguity類型呢?(Ambiguity的意思是含糊的,不明確的)

讓我們來看看get方法應該就明白了。

技術分享

一、調用父類的get也就是HashMap的get方法。

二、空值拋異常

三、Ambiguity拋異常

聰明的你應該已經明白了。

給笨笨的你解釋一下,空值拋異常就是通過這個id找不到對應的需要執行的sql語句當然就異常了;當Ambiguity拋異常就表面有兩個id相同的sql語句,mybatis不知道要執行哪一個了,所以異常了。

剩下的就是這個map是什麽時候建立的呢?當然是一開始建造工廠的時候咯,之前有講過,不明白可以翻翻前面的,復習一下咯。

具體在MappedStatement裏面sql是怎麽存放的,有興趣的可以直接進這個類看看。這裏我們就講到這裏了,要繼續主進程了。

sql的執行

我們繼續來接著之前的來看,獲得了sql之後怎麽執行的呢?

return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);

首先是誰去執行的?一個叫做executor的東西。

我們叫它執行者。它是一個接口。然後在產品生產的時候就被賦值了。

然後是它去執行的query方法,返回值是一個泛型約束的List。

然後我們來看參數:

1、ms是我們剛才獲得的執行語句。

2、wrapCollection是將當前的參數,也就是數據庫查詢的時候的入參,比如查詢條件,如果查詢條件是集合(Collection)或者數組(Array)形式的話轉換成map,如果不是就直接返回。

我們現在沒有入參,所以返回的是個null

3、rowBounds mybatis的分頁功能,我們不管他

4、Executor.NO_RESULT_HANDLER

是個null,叫做沒有結果的處理器

然後我們來看看執行

技術分享

技術分享

下面就是關鍵了!!!註意咯

技術分享

從緩存中拿我們就不看了,比較簡單,緩存其實是個map嘛

我們就看從數據庫查詢

技術分享

技術分享

下面走這個

技術分享

技術分享

看到這裏的excute沒有,這裏就是真正的執行sql了,裏面呢就是傳說中的jdbc了,喜歡你就進去看看,不喜歡我們繼續看看結果集最後是如何映射的。

對返回結果的處理

技術分享

至此整個sql在mybatis中的執行過程終於是完成了。

整條路線如果仔細來看真的很長,不得不佩服設計者如此縝密的設計。

總結

我們經過整個路線的行走,我們已經明確了sql在mybatis中執行的全部過程。

相信你也有所收獲,其實我們應該多想想設計者為何這樣設計,有的代碼為什麽要這樣寫。這樣寫的好處和設計思路又是什麽。有什麽樣的優化或者優點值得我們學習。

不過不要高興的太早。

這還沒完呢!

我們的裝備到現在還沒用上呢!後面一篇就會講解,為什麽只需要定義一個接口在mybatis中就能起作用,不需要實現類。

代理模式在其中的運用以及反射的強大。

希望上面的思路對你看源碼有幫助。如有問題還請多多提出,不勝感激。

轉載請註明出處:http://www.cnblogs.com/linkstar/category/1027239.html

作者:LinkinStar

MyBatis源碼解析【6】SqlSession運行