MyBatis原始碼窺探(一):MyBatis整體架構解析

碼出高效發表於2018-12-12

Mybatis的使用這裡就不介紹了,不知道怎麼使用的朋友可以點選

www.mybatis.org/mybatis-3/z…

這裡面的教程很詳細,包括xml的配置、對映、動態sql都有介紹,可以學習和使用,本系列的文章將會更深入的瞭解MyBatis。

1. ORM簡介

  ORM(Object Relational Mapping)物件-關係對映框架,ORM的主要功能就是根據對映配置檔案,完成資料在物件模型與關係模型之間的對映。

在這裡插入圖片描述

1.1 常見的ORM框架

1.1.1 Hibernate

  Hibernate通過hbm.xml對映檔案維護一個Java類與資料庫表的對映關係,通過Hibernate的對映,Java開發人員可以用看待Java物件的角度去看待資料庫表中的資料行,資料庫中多有的表通過hbm.xml配置檔案對映之後,都對應一個Java類。

1.1.2 JPA

  JPA(Java Persistence API) 是EJB 3.0中持久化部分的規範,他可以脫離EJB的體系單獨作為一個持久化規範進行使用。

1.1.3 Spring JDBC

  嚴格來說,Spring JDBC並不能算一個ORM框架,它僅僅是使用模板方式對原生JDBC進行了一層非常薄的封裝,使用Spring JDBC可以幫助開發人員遮蔽建立資料庫連線物件,Statement物件,異常處理以及事務管理的重複性程式碼,提高開發效率。

1.1.4 MyBatis

  MyBatis與前面介紹的持久化框架一樣,可以幫助開發人員遮蔽底層重複性的原生JDBC程式碼,MyBatis通過對映配置檔案或相應註解將ResultSet對映為Java物件,其對映規則可以巢狀其他對映規則以及子查詢,從而實現複雜的邏輯,也可實現一對一,一對多,多對多對映以及雙向對映。相比Hibemate更加輕量級,可控性也更高。

2. MyBatis整體架構

  MyBatis的整體分為三層,分別是基礎支援層,核心處理層和介面層,如圖所示

在這裡插入圖片描述

2.1 基礎支援層

  基礎支援層包含整個MyBatis的基礎模組,這些模組為核心處理層的功能提供了良好的支撐,下面簡單描述下各個模組。

2.1.1 資料來源模組

  資料來源是實際開發中常用的元件之一,現在開源的資料來源都提供了比較豐富的功能,例如連線池功能、檢測連結狀態等,選擇效能優秀的資料來源元件對於提升ORM框架乃至整個應用的效能都是非常重要的。MyBatis自身提供了相應的資料來源實現。當然MyBatis也提供了與第三方介面資料來源整合的介面,這些功能都位於資料來源模組之中。

2.1.2 事務管理模組

  MyBatis對資料庫中的事務進行了抽象,其自身提供了相應的事務介面和簡單的實現,在很多場景中,MyBatis會與Spring框架整合,並由Spring框架管理事務相關配置。

2.1.3 快取模組

  在優化系統效能時,優化資料庫效能是非常重要的一個環節,而新增快取則是優化資料庫時最有效的手段之一。正確、合理的使用快取可以將一部分資料庫請求攔截在快取這一層,這就能夠減少相當一部分資料庫的壓力。

  MyBatis中提供了一級快取和二級快取,而這兩級快取都依賴於基礎支援層中的快取模組實現,這裡需要讀者注意的是MyBatis中自帶的兩級快取以及整個應用是執行在一個JVM中的,共享一塊堆記憶體,如果這兩級快取中的資料量較大,則可能影響系統中其他功能的執行,所以當需要快取大量資料時,優先考慮使用Redis、Mongodb、Memcache等快取產品。

2.1.4 Binding模組

  在呼叫 SqISession 相應方法執行資料庫操作時,需要指定對映檔案中定義的 SQL 節點,如果出現拼寫錯誤,我們只能在執行時才能發現相應的 異常 。 為了儘早發現這種錯誤, MyBatis 通過 Binding 模組將使用者自定義的 Mapper 接 口與對映配置檔案關聯起來,系統可以通過呼叫自定義 Mapper 介面中的方法執行相應的 SQL 語句完成資料庫操作,從而避免上述問題。值得讀者注意的是,開發人員無須編寫自定義 Mapper介面的實現, MyBatis會自動為 其建立動態代理物件。在有些場景中,自定義 Mapper介面可以完全代替對映配置檔案, 但有的對映規則和 SQL 語句的定義還是寫在對映配置檔案中比較方便,例如動態 SQL 語句的定義 。

2.1.5 反射模組

  Java中的反射功能雖然強大,但對大多數開發人員來說,寫出高質量的反射程式碼還是有一定難度的。MyBatis中專門提供了反射模組,該模組對Java原生的反射進行了一系列優化,例如快取了類的後設資料,提高了反射的效能。

2.1.6 型別轉換模組

  MyBatis 為簡化配置檔案提供了別名機制 , 該機制是型別轉換模 塊的主要功能之一 。 型別轉換模組的另一個功能是實現 JDBC 型別與 Java 型別之間的 轉換,該功能在為 SQL 語句繫結實參以及 對映查詢結果集 時都會涉及。在為 SQL 語 句繫結實參時, 會將資料由 Java型別轉換成 JDBC 型別;而在對映結果集時,會將數 據由 JDBC型別轉換成 Java型別。

2.1.7 日誌模組

  無論在開發測試環境中,還是線上上生產環境中,日誌在整個系統中的地位都是非常重要的。良好的日誌功能可以幫助開發人員和測試人員快速定位 Bug程式碼,也可以幫助運維人員快速定位效能瓶頸、等問題 。 目前的 Java 世界中存在很多優秀的日誌框架,例如 Log4j、 Log4j2, slf4j等。 MyBatis作為一個設計優良的框架,除了提供詳細的日誌輸出資訊,還要能夠整合多種日誌框架,其日誌模組的 一個主要功能就是整合第三方日誌框架。

2.1.8 資源載入模組

  資源載入模組主要是對類載入器進行封裝,確定類的使用順序,並提供了載入類檔案以及其他資原始檔的功能。

2.1.9 解析器模組

  解析器模組主要提供了兩個功能:一個功能是對XPath進行封裝,為MyBatis初始化時解析mybatis-config.xml配置檔案以及對映配置檔案提供支援;另一個功能是為處理動態sql語句中的佔位符提供支援。

2.2 核心處理層

  在MyBatis的核心處理層中實現了MyBatis的核心處理流程,其中包括MyBatis的初始化以及完成一次資料庫操作的全部流程,而這些都是基於基礎支援層實現的。

2.2.1 配置解析

  在 MyBatis 初始化過程中,會載入 mybatis-config.xml 配置檔案、對映配置檔案以及 Mapper 介面中的註解資訊,解析後的配置資訊會形成相應的物件並儲存到 Configuration 物件中 。例如,節點(即ResultSet 的對映規則) 會被解析成 ResultMap 物件,定義的節點(即屬性對映)會被解析成 ResultMapping物件。之後,利用該 Configuration物件創SqlSessionFactor物件。待 MyBatis 初始化之後,開發人員可以通過初始化得到SqlSessionFactory建立 SqlSession 物件並完成資料庫操作。

2.2.2 引數對映-SQL解析

  拼湊 SQL 語句是一件煩瑣且易出錯的過程,為了將開發人員從這項枯燥無趣的工作中解脫出來,MyBatis實現動態SQL語句的功能,提供了多種動態 SQL語句對應的節點, 例如,節點、節點、節點等 。通過這些節點的組合使用,開發人員可以寫出幾乎滿足所有需求的動態 SQL語句。   MyBatis 中的scripting模組會根據使用者傳入的實參,解析對映檔案中定義的動態SQL節點,並形成資料庫可執行的SQL 語句 。之後會處理 SQL 語句中的佔位符,繫結使用者傳入的實參。

2.2.3 SQL執行

  SQL語句的執行涉及多個元件,其中比較重要的是Executor、StatementHandler、ParameterHandler和ResultSetHandler。Executor主要負責維護一級快取和二級快取,並提供事務管理的相關操作,它會將資料庫相關操作委託給StatementHandler完成。StatementHandler首先通過ParamHandler完成SQL語句的實參繫結,然後通過java.sql.Statement物件執行SQL語句並得到結果集,最後通過ResultSetHandler完成結果集的對映,得到結果物件並返回。如圖展示一條sql的執行過程:

在這裡插入圖片描述

2.2.4 外掛

  Mybatis 自身的功能雖然強大,但是並不能完美切 合所有 的應用場景,因此 MyBatis 提供了外掛介面,我們可以通過新增使用者自定義外掛的方式對 MyBatis 進行擴充套件。用 戶自定義外掛也可以改變 Mybatis 的預設行為 ,例如,我們可以 攔截 SQL 語句並對其 進行重寫。由於使用者自定義外掛會影響 MyBatis 的核心行為,在使用自定義外掛之前, 開發人員需要了解 MyBatis 內部的原理,這樣才能編寫出安全、高效的外掛。

3.MyBatis 核心類介紹

SqlSession            作為MyBatis工作的主要頂層API,表示和資料庫互動的會話,完成必要資料庫增刪改查功能
Executor              MyBatis執行器,是MyBatis 排程的核心,負責SQL語句的生成和查詢快取的維護
StatementHandler      封裝了JDBC Statement操作,負責對JDBC statement 的操作,如設定引數、將Statement結果集轉換成List集合。
ParameterHandler      負責對使用者傳遞的引數轉換成JDBC Statement 所需要的引數,
ResultSetHandler      負責將JDBC返回的ResultSet結果集物件轉換成List型別的集合;
TypeHandler           負責java資料型別和jdbc資料型別之間的對映和轉換
MappedStatement       MappedStatement維護了一條<select|update|delete|insert>節點的封裝, 
SqlSource             負責根據使用者傳遞的parameterObject,動態地生成SQL語句,將資訊封裝到BoundSql物件中,並返回
BoundSql              表示動態生成的SQL語句以及相應的引數資訊
Configuration         MyBatis所有的配置資訊都維持在Configuration物件之中。
複製程式碼

4. MyBatis執行流程

在這裡插入圖片描述
到這裡本篇文章就結束,此篇文章作為MyBatis系列開篇,這裡只是做一個整體的介紹,後面會陸續對Mybatis的各個模組進行分析。喜歡的朋友可以關注一波,跟著我一起學習MyBatis。

相關文章