我們都知道Mybatis
是一個非常小巧靈活的ORM框架,深受國內廣大開發者的喜愛,我們知道它的出現某種程度是為了消除所有的JDBC代碼和參數的手工設置以及結果集的封裝問題;基於這個一點,我們就可以知道MyBatis
實際上就是對JDBC的封裝,所以這節我們就來看下MyBatis
是怎樣對JDBC封裝的,從而可以借鑒學習其他優秀框架在解決問題之初從架構設計層面的思考,然后通過執行流程分析,進一步深刻理解Mybatis
的工作原理。
首先我們先來了解下MyBatis
的架構設計
MyBatis
總共把功能架構分成了四部分:
接口層
提供給外部使用的接口API,開發人員通過這些本地API來操縱數據庫。接口層一接收到調用請求就會調用數據處理層來完成具體的數據處理, Mybatis
提供了兩種方式
- 下面的這些方法就是在
SqlSession
接口中提供的接口方法
<T> T selectOne(String statement,Object parameter);
<E>List<E> selectList(String statement,Object parameter);
int insert(String statement,Object parameter);
int update(String statement,Object parameter);
int delete(String statement,Object parameter);
- Mapper代理的方式
Mapper 代理的方式實際上就是通過創建接口(UserMapper 接口)的代理對象調用接口中的方法,最終執行方法調用是 Executor 對象,底層其實還是調用的傳統的 API 方法。
數據處理層
數據處理層這部分主要就 JDBC 的核心內容了,包括參數映射、類型轉換、SQL 解析、 SQL 執行以及結果的封裝,這部分內容就可以理解成 JDBC 的核心內容,這里有幾個重要類
- ParameterHandler∶ SQL的參數處理
- ResultSetHandler∶ 結果集處理
- StatementHandler:封裝了JDBC Statement操作,設置參數,轉換結果集
- Executor∶ MyBatis 的執行器,用於執行增刪改查操作
SQL解析
MyBatis支持兩種 SQL
解析的方式,一種 xml、一種是注解;兩種方式對於一些基礎的 CRUD 區別不大,使用注解來映射簡單語句會使代碼顯得更加簡潔,但對於稍微復雜一點的語句, Java 注解不僅力不從心,還會讓你本就復雜的 SQL 語句更加混亂不堪。因此,如果你需要做一些很復雜的操作,最好用 XML來映射語句
框架支撐層
這部分主要是框架抽取出來的通用組件包括數據源管理、事務管理、配置加載和緩存處理;為上層的數據處理層提供最基礎的支撐
- 數據源管理
數據源的管理對於持久層的框架來說,可謂是非常的重要,稍有不慎就會浪費大量系統資源,MyBatis 也對此做了很好的支持, MyBatis 有三種內建的數據源類型 UNPOOLED、 POOLED 、 JNDI- UNPOOLED-這個數據源的實現會每次請求時打開和關閉連接
- POOLED-這種數據源的實現利用"池"的概念,將 JDBC 連接對象組織起來,避免了創建新的連接實例時所必需的初始化和認證時間
- JNDI-這個數據源實現是為了能在如 EJB 或應用服務器這類容器中使用,容器可以集中或在外部配置數據源,然后放置一個 JNDI上下文的數據源引用。這種已經不用了
通常情況下,我們是會使用 POOLED 的,他可以幫我們節省很多寶貴的系統資源
- 事務管理(transactionManager)
在 MyBatis 中有兩種類型的事務管理器(JDBC
/MANAGED
)它通過一個頂層的Transaction
接口以及其不同實現JdbcTransaction
和ManagedTransaction
來實現對事務的管理∶- JDBC-這個配置直接使用了 JDBC 的提交和回滾設施,它依賴從數據源獲得的連接來管理事務作用域,對應的實現類
JdbcTransaction
- MANAGED-這個配置幾乎沒做什么。它從不提交或回滾一個連接,而是讓容器來管理事務的整個生命周期(比如 JEE 應用服務器的上下文),對應的實現類
ManagedTransaction
- JDBC-這個配置直接使用了 JDBC 的提交和回滾設施,它依賴從數據源獲得的連接來管理事務作用域,對應的實現類
對事務的管理,在和 Spring
整合之后,通常會用 Spring
的事務管理器
- 緩存處理
緩存對於持久層框架來說還是非常重要的,一定程度上可以減少和數據庫的交互, MyBatis 的提供了兩種緩存機制,一級緩存和二級緩存- 一級緩存∶ 是 SqlSession 級別的緩存,也就是會話級別的,如果兩個相同的查詢,第二次的查詢會直接先從緩存中去拿,一級緩存也是默認開啟的,這部分我們在源碼分析的內容里會詳細分析
- 二級緩存:是 Mapper 級別的緩存,也就是一個 xxx.xml 內的查詢是可以共用的,需要手動開啟
引導層
這部分是 MyBatis
啟動時核心配置文件的方式,嚴格來說也可以不算在架構層面,不過MyBatis
也是提供了兩種方式,一個是xml的方式,也是用的比較多的,一種是使用 Java API的方式比如在配置環境的時候
- xml的方式
<?xmL version="1.0" encoding="UTF-8" ?><!DOCTYPE configuration
PUBLIC"-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<!--省略-->
</environment>
</environments>
</configuration>
- Java API的方式
Environment environment = new Environment("development",transactionFactory,dataSource);
Configuration configuration = new Configuration(environment)) ;
雖然 MyBatis
提供這兩種方式,但是一般情況下還是使用 xml 的比較方便
小結:
這節內容主要從整體架構上分析了 Mybatis
的架構設計,實際上是對JDBC的做了一些抽取和封裝,主要分成了三層
- API接口層
- 數據處理層
- 框架通用模塊