MyBatis的執(zhí)行流程詳解,值得收藏!
來源:北大青鳥總部
2020年06月16日 13:44
摘要:
MyBatis的執(zhí)行流程詳解
說到流程這個(gè)事兒,大家可能最先想到的就是富士康的流水線,標(biāo)準(zhǔn)化的分工讓每道工序都如絲一般潤滑,所以才成就了富士康"世界工廠"的名號。
想當(dāng)年猿小二也是眾多流水線工人中的一員,每天成百上千次的重復(fù)著同一個(gè)動作;突然有一天猿小二頓悟了,他認(rèn)為我不能在這里浪費(fèi)青春,我要去改變世界,于是他決定學(xué)習(xí)Java,沒想到這可一發(fā)不可收拾,學(xué)起Java來,如久旱逢甘霖,如魚得水一樣的輕松順暢。
但是好景不長,最近他就在學(xué)習(xí)MyBatis這里遇到了點(diǎn)小麻煩,總是搞不清楚,MyBatis是怎么一個(gè)接口、一個(gè)映射文件(寫sql)就可以操作數(shù)據(jù)庫了呢?它的執(zhí)行流程到底是怎么樣的呢?帶著這樣的疑問,猿小二開始了他的探索....
說到MyBatis執(zhí)行流程,估計(jì)80%的程序員可能每天都沉浸在一個(gè)接口方法、一條SQL快樂的coding中,也可能他們都在忙著陪女朋友(可能性不大,因?yàn)槌绦騿T沒有女朋友),也可能是沒有時(shí)間研究;也可能覺得使用起來很簡單,不就是加載配置文件,執(zhí)行SQL嗎,soeasy;但是作為一個(gè)勵(lì)志成為優(yōu)秀工程師的程序猿,僅僅停留在這個(gè)層面還遠(yuǎn)遠(yuǎn)不夠,它根本滿足不了我們對技術(shù)的渴望。
我們都知道MyBtis是對JDBC的簡易封裝,它的出現(xiàn)某種程度了是為了消除所有的JDBC代碼和參數(shù)的手工設(shè)置以及結(jié)果集的封裝問題;不管怎樣,JDBC的那一套還是不會變的,只是做了抽象、封裝、歸類等;所以想要理解MyBatis的執(zhí)行流程,那就不得不先回顧一下JDBC的執(zhí)行流程。
注冊驅(qū)動
獲取Connection連接
執(zhí)行預(yù)編譯
執(zhí)行SQL
封裝結(jié)果集
釋放資源
以上就是JDBC操作數(shù)據(jù)的流程步驟,然后我看下MyBatis的執(zhí)行流程圖。
上面流程就是MyBatis內(nèi)部核心流程,咱們來一步步解釋下,根據(jù)圖中步驟,我們可以將這個(gè)執(zhí)行流程分成了8個(gè)步驟。
讀取MyBatis的核心配置文件。mybatis-config.xml為MyBatis的全局配置文件,用于配置數(shù)據(jù)庫連接、屬性、類型別名、類型處理器、插件、環(huán)境配置、映射器(mapper.xml)等信息,這個(gè)過程中有一個(gè)比較重要的部分就是映射文件其實(shí)是配在這里的;這個(gè)核心配置文件最終會被封裝成一個(gè)Configuration對象
加載映射文件。映射文件即SQL映射文件,該文件中配置了操作數(shù)據(jù)庫的SQL語句,映射文件是在mybatis-config.xml中加載;可以加載多個(gè)映射文件。常見的配置的方式有兩種,一種是package掃描包,一種是mapper找到配置文件的位置。
<!-- 使用包路徑,掃描包下所有的接口,這種方式比較方便 -->
<package name="com.mybatis.demo"/> <!-- resource:使用相對路徑的資源引用--><!-- url:使用絕對類路徑的資源引用--><!-- class:使用映射器接口實(shí)現(xiàn)類的完全限定類名--><mapper resource="xxx.xml"/>
構(gòu)造會話工廠獲取SqlSessionFactory。這個(gè)過程其實(shí)是用建造者設(shè)計(jì)模式使用SqlSessionFactoryBuilder對象構(gòu)建的,SqlSessionFactory的最佳作用域是應(yīng)用作用域。
// 2. 創(chuàng)建SqlSessionFactory對象實(shí)際創(chuàng)建的是DefaultSqlSessionFactory對象SqlSessionFactory builder = new SqlSessionFactoryBuilder().build(inputStream);
創(chuàng)建會話對象SqlSession。由會話工廠創(chuàng)建SqlSession對象,對象中包含了執(zhí)行SQL語句的所有方法,每個(gè)線程都應(yīng)該有它自己的 SqlSession 實(shí)例。SqlSession的實(shí)例不是線程安全的,因此是不能被共享的,所以它的最佳的作用域是請求或方法作用域。
// 3. 創(chuàng)建SqlSession對象實(shí)際創(chuàng)建的是DefaultSqlSession對象
SqlSession sqlSession = builder.openSession();
Executor執(zhí)行器。是MyBatis的核心,負(fù)責(zé)SQL語句的生成和查詢緩存的維護(hù),它將根據(jù)SqlSession傳遞的參數(shù)動態(tài)地生成需要執(zhí)行的SQL語句,同時(shí)負(fù)責(zé)查詢緩存的維護(hù)
SimpleExecutor -- SIMPLE 就是普通的執(zhí)行器。
ReuseExecutor -執(zhí)行器會重用預(yù)處理語句(PreparedStatements)
BatchExecutor --它是批處理執(zhí)行器
MappedStatement對象。MappedStatement是對解析的SQL的語句封裝,一個(gè)MappedStatement代表了一個(gè)sql語句標(biāo)簽,如下:
<!--一個(gè)動態(tài)sql標(biāo)簽就是一個(gè)`MappedStatement`對象--><select id="selectUserList" resultType="com.mybatis.User">
select * from t_user</select>
輸入?yún)?shù)映射。輸入?yún)?shù)類型可以是基本數(shù)據(jù)類型,也可以是Map、List、POJO類型復(fù)雜數(shù)據(jù)類型,這個(gè)過程類似于JDBC的預(yù)編譯處理參數(shù)的過程,有兩個(gè)屬性 parameterType和parameterMap
封裝結(jié)果集??梢苑庋b成多種類型可以是基本數(shù)據(jù)類型,也可以是Map、List、POJO類型復(fù)雜數(shù)據(jù)類型。封裝結(jié)果集的過程就和JDBC封裝結(jié)果集是一樣的。也有兩個(gè)常用的屬性resultType和resultMap。
我們再來看一下這個(gè)完整的執(zhí)行步驟,代碼如下:
/*** Mybatis測試*/public class MybatisTest {public static void main(String[] args) throws Exception { // 1.加載配置文件
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); // 2. 創(chuàng)建SqlSessionFactory對象實(shí)際創(chuàng)建的是DefaultSqlSessionFactory對象
SqlSessionFactory builder = new SqlSessionFactoryBuilder().build(inputStream); // 3. 創(chuàng)建SqlSession對象實(shí)際創(chuàng)建的是DefaultSqlSession對象
SqlSession sqlSession = builder.openSession(); // 4. 創(chuàng)建代理對象
UserMapper mapper = sqlSession.getMapper(UserMapper.class); // 5. 執(zhí)行查詢語句
List<User> users = mapper.selectUserList(); // 6. 釋放資源
sqlSession.close();
inputStream.close();
}
}
通過分析Mybatis的執(zhí)行流程,我們可以發(fā)現(xiàn)它和JDBC基本大同小異,比較明顯的地方就是:
注冊驅(qū)動獲取鏈接的部分都抽取到了核心配置文件mybatis-config.xml中。
sql語句抽取到了映射文件mapper.xml中。
至于其他的部分,如執(zhí)行sql預(yù)編譯、執(zhí)行查詢、封裝結(jié)果集等都是抽取到了其他的類中來完成這些操作。通過對JDBC執(zhí)行步驟來對比分析MyBatis的執(zhí)行的流程,總體上來看它們的執(zhí)行步驟基本是一樣的,所以大家是不是覺得MyBatis這個(gè)框架其實(shí)也挺簡單的,總結(jié)下其實(shí)就是:
加載解析配置文件(核心配置文件和映射文件)
處理參數(shù)
執(zhí)行查詢
封裝結(jié)果集