MyBatis原理解析

程序员多多發表於2024-03-14

MyBatis入門的四行程式碼

  //<1> 載入配置檔案
  InputStream is = Resources.getResourceAsStream("mybatis.xml");
  //<2> 建立sessionFactory物件
  sessionFactory = new SqlSessionFactoryBuilder().build(is);
  //<3> 獲取sqlSession物件資訊
  SqlSession session = factoy.openSqlSession()
  //<4> 構建對映器的代理物件
  UserMapper mapper = session.getMapper(UserMapper.class);
  // .....呼叫相關方法資訊

前言

MyBatis是一款ORM(Object-Relational Mapping)框架,其主要用於將Java物件與關聯式資料庫之間進行對映,憑藉其輕量性、穩定性以及廣泛的開源社群其受到了廣大開發者的追捧。
那MyBatis為我們做了哪些事情呢?其實,總結來看主要有如下幾點:

SQL對映配置:MyBatis使用XML或註解配置檔案來定義SQL查詢、插入、更新和刪除操作,以及與資料庫表之間的對映關係。這使得開發者能夠將SQL語句與Java程式碼分離,提高了程式碼的可維護性。
動態SQL:MyBatis支援動態SQL,允許根據不同的條件生成不同的SQL語句。這使得構建複雜的查詢變得更加靈活和方便。
引數對映:MyBatis能夠將Java物件的屬性與SQL語句中的引數進行對映,無需手動編寫繁瑣的引數傳遞程式碼。
結果集對映:MyBatis支援將SQL查詢結果對映到Java物件,自動將資料庫表中的列值賦給Java物件的屬性,大大簡化了資料的讀取和處理。
事務管理:MyBatis可以與Java的事務管理框架(如Spring)無縫整合,確保資料庫操作的原子性和一致性。
連線池整合:MyBatis可以與常見的Java連線池庫(如Apache DBCP、C3P0、HikariCP)整合,以管理資料庫連線的獲取和釋放。
二級快取:MyBatis支援二級快取,可以在多個會話之間共享資料,提高效能。

總覽MyBatis

對於Mybatis的架構大致可以分為三層:基礎支援層、核心處理層和介面層。
image

或許,你會覺得上圖過於複雜,難以理解。如果此刻你也有這樣的疑惑,不要慌。不妨跟著筆者思路來進行梳理。
首先,使用MyBatis概括來看大致包括如下幾步:

  1. 定義介面,配置相關的xml檔案資訊
  2. 載入介面的配置檔案,解析相關配置檔案
  3. 生成介面代理類,執行相關sql

由於在使用MyBatis過程中會編寫相關的配置檔案,所以Mybatis內部必然需要相應元件來支撐配置檔案的解析,這些也就構成了底層的基礎支撐層。既然會解析配置檔案,那是不是必然會涉及到資源載入、配置解析等模組?
進一步,當配置檔案解析完成後,下一步就是生成代理,然後執行sql,此時所涉及的也就是核心處理層中的sql執行,sql解析等。更進一步,執行sql過程中為了避免Connection頻繁建立,是不是需要對連線進行池化操作?所以MyBatis內部會抽象出一個資料來源模組來統一管理連線。
除此之外,對於sql執行過程中的事務是不是也需要控制?所以MyBatis還有事務管理模組來對sql執行過程中的事務進行管理。
事實上,你只需要記住Mybatis的使用過程為:定義介面,提供配置檔案,而後生成代理,執行Sql 即可。以此進行發散,自然而然能擴充套件出上圖所示內容,根本沒必要死記硬背。
熟悉了MyBatis的整體架構後,我們接下來看Mybatis內部執行sql的大致流程:

image
接下來,我們將主要圍繞這張圖中內容進行總結分析。

配置檔案解析

配置檔案解析過程大致如下所示:
image

事實上,MyBatis內部對於配置檔案解析的過程可以概括如下:

  1. 載入配置檔案:MyBatis首先載入主配置檔案(通常是mybatis-config.xml),並建立一個Configuration物件來表示整個MyBatis配置。
  2. 解析主配置檔案:MyBatis使用XML解析器解析主配置檔案,該檔案包含了關於資料來源、外掛、型別別名、快取等全域性配置資訊。這些配置會被儲存在Configuration物件中。

而參與配置檔案解析的都繼承與BaseBuilder,其體系結構如下所示:
image

其中

  1. XMLStatementBuilder:這個類用於解析對映檔案中的<select>、<insert>、<update> 等標籤,構建與 SQL 語句相關的物件(如 MappedStatement),包括 SQL 語句的解析、引數對映、結果對映等。
  2. XMLMapperBuilder:XMLMapperBuilder 用於解析對映檔案(通常是 Mapper.xml 檔案),負責構建與對映檔案相關的物件,包括對映檔案的解析、SQL 語句的構建、引數對映、結果對映、快取配置等。
  3. XMLConfigBuilder:XMLConfigBuilder 用於解析主配置檔案(通常是 mybatis-config.xml 檔案),負責構建與全域性配置相關的物件,包括資料來源配置、型別別名配置、外掛配置、快取配置等。

總結來看,對於MyBatis的載入過程來說,其在處理配置檔案資訊時,首先,會傳遞配置檔案所在位置資訊,然後再呼叫框架提供的SqlSessionFactory的build方法便會根據傳入路徑資訊去載入相關的配置檔案,並進行解析。而解析的內容會存放到的configuration之中,進而方便後續元件的使用。

代理構建

當配置檔案解析,下一步就是透過SqlSession的getMapper方法來構建一個介面對應的代理類,這一過程大致如下:

image

這一過程中涉及的元件主要包括MapperProxyFactory、MapperRegistry、MapperProxy,更加詳細的分析可參考Mybatis流程分析(六): Mybatis中方法和sql語句的橋樑——MapperProxy, 總之這一過程的本質就是透過Jdk動態代理的方式返回一個實現介面的例項物件

sql執行

當配置檔案解析完成,介面相應的代理類構建完畢後,下一步要做的就是sql的執行,這一過程邏輯大致如下所示:
image

這一部分的底層邏輯就是原生JDBC操縱資料庫的那一套邏輯,即

  1. 建立SQL語句:即建立Statement、PreparedStatement或CallableStatement物件,分別用於執行不同型別的SQL語句。
  2. 執行SQL查詢:使用建立的Statement或PreparedStatement物件來執行SQL查詢。
    處理查詢結果:透過ResultSet物件來處理查詢的結果資料。

總結
最後,我們再來一下Mybatis內部對於sql執行的大致步驟:

  1. 建立 SqlSessionFactory:使用Mybatis首先需要建立一個 SqlSessionFactory 物件,這通常透過讀取MyBatis 的主配置檔案(mybatis-config.xml)並使用 SqlSessionFactoryBuilder 來實現。SqlSessionFactory 負責建立資料庫連線和 SqlSession 物件。
  2. 建立 SqlSession:透過 SqlSessionFactory 建立一個 SqlSession 物件。SqlSession 代表了與資料庫的一次會話,它可以執行 SQL 操作並管理資料庫連線。通常,每個執行緒都會建立自己的 SqlSession。
  3. 執行 SQL 語句:在 SqlSession 中,透過呼叫方法執行 SQL 語句。MyBatis 支援多種方式來執行 SQL,包括 selectOne()、selectList()、insert()、update()、delete() 等方法。
  4. SQL 語句解析:MyBatis 會解析 SQL 語句,包括動態 SQL,引數對映和結果對映。這包括了將 Java 物件轉化為 SQL 語句中的引數,以及將查詢結果對映回Java物件。
  5. 執行 SQL:MyBatis 將 SQL 語句傳送到資料庫,並執行相應的操作,如查詢、插入、更新或刪除。資料庫返回結果或受影響的行數,這取決於SQL語句的型別。
  6. 處理結果:MyBatis 最終會將SQL的執行結果對映為 Java 物件,然後返回給呼叫者。對映過程通常基於對映檔案中的配置。結果集的處理包括將資料庫查詢結果對映為 Java 物件的屬性值。
    進一步,上述步驟可總結概括總結為如下的流程。
    image

相關文章