?
? ?
??核心關系:?? MyBatis-Plus ??不是?? MyBatis 的替代品,而是構建在 MyBatis ??之上??的一個強大的??增強工具包??。它完全兼容原生 MyBatis,并在其基礎上提供了大量開箱即用的功能,極大地簡化了開發,尤其是單表操作。
??一、 MyBatis 核心原理??
MyBatis 的核心思想是將 ??SQL 語句從 Java 代碼中解耦??,通過配置或注解來管理 SQL,并提供靈活的 ORM 映射。其核心原理圍繞以下幾個關鍵組件和流程:
??
SqlSessionFactoryBuilder
&SqlSessionFactory
:??- ??作用:?? 應用啟動時,讀取 MyBatis 的全局配置文件 (
mybatis-config.xml
) 和所有的 Mapper XML 文件(或注解配置)。 - ??原理:??
SqlSessionFactoryBuilder
解析這些配置文件,構建出包含所有配置信息(數據源、事務管理器、類型處理器、插件、Mapper 注冊信息等)的Configuration
對象,并最終創建出SqlSessionFactory
。SqlSessionFactory
是生產SqlSession
的工廠。
- ??作用:?? 應用啟動時,讀取 MyBatis 的全局配置文件 (
??
SqlSession
:??- ??作用:?? 代表一次與數據庫的會話。它是 MyBatis 工作的??核心入口??。
- ??原理:?? 通過
SqlSessionFactory.openSession()
獲取。它提供了執行 SQL 命令(selectOne
,selectList
,insert
,update
,delete
)、獲取 Mapper 接口代理對象、管理事務等方法。每個SqlSession
通常對應一個數據庫連接(或連接池中的一個連接)。
??
Executor
:??- ??作用:??
SqlSession
內部真正??執行 SQL 操作??的組件。 - ??原理:??
SqlSession
將請求委托給Executor
。Executor
負責維護一級緩存(SqlSession
級別)、處理延遲加載、調用StatementHandler
等。常見的實現有SimpleExecutor
(每次執行創建新Statement
)、ReuseExecutor
(重用Statement
)、BatchExecutor
(批處理)。
- ??作用:??
??
StatementHandler
:??- ??作用:?? 負責??創建 JDBC
Statement
對象??(PreparedStatement
,CallableStatement
,Statement
),并??設置參數??、??執行 SQL??。 - ??原理:??
Executor
調用StatementHandler
。它使用ParameterHandler
將 Java 對象參數設置到 SQL 的占位符 (?
) 上。
- ??作用:?? 負責??創建 JDBC
??
ParameterHandler
:??- ??作用:?? 負責將??用戶傳入的 Java 參數??,按照 SQL 語句中的占位符 (
?
) 進行??類型轉換和設置??。 - ??原理:?? 利用注冊的
TypeHandler
完成 Java 類型到 JDBC 類型的轉換。
- ??作用:?? 負責將??用戶傳入的 Java 參數??,按照 SQL 語句中的占位符 (
??
TypeHandler
:??- ??作用:?? 負責 ??Java 類型和 JDBC 類型之間的相互轉換??。
- ??原理:?? MyBatis 內置了常用類型(如 String, Integer, Date 等)的處理器。用戶可以自定義處理器處理特殊類型(如枚舉)。
??
ResultSetHandler
:??- ??作用:?? 負責將 JDBC
ResultSet
返回的結果集??轉換??為??指定的 Java 對象??(單個對象、List、Map 等)。 - ??原理:?? 根據 Mapper 方法定義的返回類型(或
resultMap
配置),利用TypeHandler
和反射,將結果集的每一行數據映射成 Java 對象。
- ??作用:?? 負責將 JDBC
??
MappedStatement
:??- ??作用:?? 代表一個映射的 SQL 語句。它是 MyBatis 配置的核心單元。
- ??原理:?? 存儲了 SQL 語句本身(
<select>
,<insert>
等標簽的內容)、參數映射信息 (<parameterMap>
或@Param
)、結果映射信息 (<resultMap>
或@Result
)、SQL 命令類型(SELECT/INSERT 等)、緩存配置等。一個 Mapper 接口方法對應一個MappedStatement
。
??配置方式:??
- ??XML 配置:?? 主要方式。通過
mybatis-config.xml
配置全局設置,通過Mapper.xml
文件定義 SQL 和映射關系。 - ??注解配置:?? 在 Mapper 接口方法上使用
@Select
,@Insert
,@Update
,@Delete
,@Results
等注解直接編寫 SQL 和映射規則。通常用于簡單 SQL。
- ??XML 配置:?? 主要方式。通過
??MyBatis 工作流程總結:??
- 應用啟動:解析配置 -> 構建
Configuration
-> 創建SqlSessionFactory
。 - 業務請求:
SqlSessionFactory
-> 創建SqlSession
。 - 執行操作:
- 通過
SqlSession
直接執行 SQL 方法 (selectOne
,update
等)。 - 或通過
SqlSession.getMapper()
獲取 Mapper 接口的??動態代理對象??。
- 通過
- 代理對象調用:代理對象根據方法名找到對應的
MappedStatement
。 Executor
執行:Executor
根據MappedStatement
信息,調用StatementHandler
創建Statement
。ParameterHandler
設置參數。StatementHandler
執行 SQL。ResultSetHandler
處理結果集,映射為 Java 對象。- 返回結果。
??優點:?? 靈活、SQL 可控性強、與 JDBC 解耦、支持復雜映射、插件擴展性強。
??缺點:?? 需要編寫大量 SQL 和 XML/注解(尤其是簡單 CRUD)、配置繁瑣。
??二、 MyBatis-Plus (MP) 核心原理??
MP 的核心原理是在 ??MyBatis 原有架構和機制的基礎上??,通過一系列封裝、擴展和自動化技術,??極大地簡化單表操作和常用功能開發??。它沒有改變 MyBatis 的核心流程,而是增強了它。
??核心增強點:
BaseMapper
與SqlInjector
/AbstractMethod
??- ??原理:?? MP 的核心創新。用戶 Mapper 接口只需繼承
BaseMapper
。在應用啟動時,MP 的SqlInjector
(如DefaultSqlInjector
) 會掃描這些 Mapper。 - ??動態 SQL 生成:?? 對于
BaseMapper
中的每個方法(insert
,selectById
,update
等),MP 都有一個對應的AbstractMethod
子類(如Insert
,SelectById
,Update
)。這些子類在啟動時,利用實體類的元數據 (TableInfo
,由@TableName
,@TableId
等注解解析而來) 和預定義的 SQL 模板 (SqlMethod
),??動態生成??該方法的完整 SQL 語句和MappedStatement
對象,并注冊到 MyBatis 的Configuration
中。 - ??結果:?? 開發者無需為這些通用方法編寫任何 SQL 或 XML,MP 自動提供實現。
- ??原理:?? MP 的核心創新。用戶 Mapper 接口只需繼承
??強大的條件構造器 (
Wrapper
)??- ??原理:?? 提供
QueryWrapper
,UpdateWrapper
,LambdaQueryWrapper
等。用戶通過鏈式調用構建復雜的查詢/更新條件(eq
,like
,between
,set
等)。 - ??SQL 拼接:??
Wrapper
內部將條件表達式存儲為結構化的數據。當Wrapper
被用于查詢或更新方法時,MP 的 SQL 生成引擎會安全地(防止 SQL 注入)將這些條件??解析并拼接到自動生成的基礎 SQL 的WHERE
子句或SET
部分??。
- ??原理:?? 提供
??自動配置與 Starter (Spring Boot)??
- ??原理:?? 提供
mybatis-plus-boot-starter
。利用 Spring Boot 自動配置機制,自動創建和配置DataSource
,SqlSessionFactoryBean
(注入 MP 的核心組件如GlobalConfig
,Interceptor
),MapperScannerConfigurer
等,大大簡化了集成步驟。
- ??原理:?? 提供
??插件體系增強??
- ??原理:?? 繼承并擴展 MyBatis 的
Interceptor
接口,提供功能更強大、開箱即用的內置插件:PaginationInnerInterceptor
: 自動處理物理分頁(生成 COUNT 查詢和分頁 SQL)。OptimisticLockerInnerInterceptor
: 自動實現樂觀鎖(基于@Version
注解)。BlockAttackInnerInterceptor
: 防止全表更新/刪除(安全防護)。DynamicTableNameInnerInterceptor
: 動態表名。IllegalSQLInnerInterceptor
: SQL 性能分析/阻止惡意 SQL。
- ??工作方式:?? 這些插件在 MyBatis 的執行流程(主要是
Executor
階段)進行攔截,添加額外功能。
- ??原理:?? 繼承并擴展 MyBatis 的
??全局配置與元數據處理??
GlobalConfig
: 存儲全局配置(表前綴、主鍵生成器策略、元對象處理器等)。MetaObjectHandler
: 實現??自動填充??功能(@TableField(fill = ...)
)。在插入或更新時,通過反射自動填充字段(如createTime
,updateTime
)。
??注解驅動增強??
- ??原理:?? 在 MyBatis 注解基礎上,提供更豐富的 ORM 和功能注解:
@TableName
: 指定表名。@TableId
: 指定主鍵及策略(自增、UUID、雪花ID等)。@TableField
: 指定字段映射、自動填充策略、是否存在等。@Version
: 樂觀鎖版本字段。@EnumValue
: 枚舉值映射。@TableLogic
: 邏輯刪除標記。@SqlParser
: 過濾 SQL 解析(用于跳過某些攔截器)。
- 這些注解信息在啟動時被解析并存儲在
TableInfo
等元數據對象中,供 SQL 生成、條件構造、插件等使用。
- ??原理:?? 在 MyBatis 注解基礎上,提供更豐富的 ORM 和功能注解:
??MP 工作流程總結:??
- ??啟動階段:??
- 自動配置(Spring Boot Starter)。
- 掃描實體類注解,構建
TableInfo
等元數據。 - 掃描 Mapper 接口(繼承
BaseMapper
)。 SqlInjector
為BaseMapper
的每個方法注入對應的AbstractMethod
實現。AbstractMethod
子類利用元數據和 SQL 模板,動態生成MappedStatement
并注冊。- 配置并添加 MP 的內置插件到
InterceptorChain
。
- ??運行時階段:??
- 與原生 MyBatis 流程基本相同(
SqlSession
->Executor
-> ...)。 - 當調用
BaseMapper
方法時,執行的是 MP 動態生成的MappedStatement
。 - 當使用
Wrapper
時,MP 在生成 SQL 時會解析并拼接Wrapper
的條件。 - MP 的插件在相應執行點進行攔截,提供分頁、樂觀鎖等功能。
- 與原生 MyBatis 流程基本相同(
??優點:?? 極大簡化 CRUD、減少 SQL/XML 編寫、內置強大功能(分頁、代碼生成器、樂觀鎖、邏輯刪除等)、增強條件構造、提高開發效率。
??缺點:?? 對復雜 SQL 和多表關聯查詢的支持不如直接手寫 SQL/XML 靈活(雖然也能用),需要學習 MP 特有的 API 和注解。
??三、 MyBatis vs MyBatis-Plus 核心對比總結??
特性 | MyBatis | MyBatis-Plus (MP) | 說明 |
---|---|---|---|
??定位?? | 靈活的 SQL 映射框架 | MyBatis 的增強工具包 | MP 基于 MyBatis,不是替代品。 |
??核心目標?? | SQL 與代碼解耦,靈活控制 SQL | ??簡化開發??,尤其是單表 CRUD | MP 專注于減少樣板代碼。 |
??SQL 編寫?? | ??必需?? (XML 或注解) | ??可選?? (對單表 CRUD 自動生成) | MP 的 BaseMapper 自動提供通用方法實現。復雜 SQL 仍需手寫。 |
??CRUD 實現?? | 手動編寫每個 CRUD 方法的 SQL 和映射 | ??自動實現?? BaseMapper 中的通用 CRUD 方法 | MP 的核心優勢,省去大量簡單 SQL 編寫。 |
??條件構造?? | 手動拼接 SQL 條件字符串 (易錯,不安全) | 強大的 ??Wrapper API?? (鏈式調用,類型安全 - LambdaWrapper,防注入) | MP 提供面向對象的、安全的條件構建方式。 |
??分頁?? | 需手動編寫分頁 SQL (不同數據庫語法不同) | 內置 ??PaginationInterceptor ?? (自動物理分頁) | MP 的分頁插件自動處理不同數據庫方言、COUNT 查詢和數據獲取。 |
??主鍵生成?? | 需在 SQL 或配置中處理 | 支持多種策略 (@TableId ),內置分配器 (雪花ID等) | MP 簡化了主鍵管理。 |
??邏輯刪除?? | 需手動在 SQL 中添加條件 | 內置支持 (@TableLogic ),自動添加過濾條件 | MP 自動在查詢/更新中處理邏輯刪除字段。 |
??樂觀鎖?? | 需手動實現版本控制邏輯 | 內置支持 (@Version ),通過插件自動處理 | MP 簡化了樂觀鎖實現。 |
??自動填充?? | 需手動在代碼中設置 | 內置支持 (@TableField(fill) + MetaObjectHandler ) | MP 自動填充如創建時間、更新時間等字段。 |
??代碼生成器?? | 無官方提供,需用第三方或自研 | 提供功能強大的 ??代碼生成器?? | MP 可快速生成 Entity, Mapper, Service, Controller 等基礎代碼。 |
??安全防護?? | 無內置 | 提供 ??BlockAttackInnerInterceptor ?? 等安全插件 | MP 防止全表更新/刪除等危險操作。 |
??配置復雜度?? | 相對較高 (需配置較多 XML/注解) | ??顯著降低?? (尤其結合 Spring Boot Starter) | MP 的自動配置和默認行為減少了大量配置。 |
??學習曲線?? | 掌握 SQL/XML 映射和核心組件即可 | 需額外學習 MP 特有的 API (Wrapper , BaseMapper ), 注解和插件 | MP 增加了自己的抽象層。 |
??靈活性?? | ??極高??,完全掌控 SQL | 對單表操作靈活,對??復雜 SQL/多表?? 靈活性相對降低 | MP 處理復雜場景時,有時仍需回退到原生 MyBatis 方式 (手寫 SQL/XML)。 |
??適用場景?? | 需要極致 SQL 控制、復雜查詢、存儲過程調用 | 快速開發、大量單表操作、需要內置功能 (分頁/樂觀鎖等) | 兩者并非互斥,可在同一項目中結合使用。 |
??總結:??
- ??MyBatis:?? 是??基礎??,提供了靈活、強大的 SQL 映射能力,將開發者從 JDBC 的繁瑣中解放出來,但需要編寫大量 SQL 和配置。
- ??MyBatis-Plus:?? 是??增強??,在 MyBatis 的基礎上,通過自動化生成、強大的條件構造器、豐富的內置功能(分頁、代碼生成、樂觀鎖等)和便捷的配置(特別是 Spring Boot),??極大地提升了開發效率,尤其擅長處理單表操作??。它保留了 MyBatis 的靈活性,對于復雜場景,你仍然可以像使用原生 MyBatis 一樣編寫自定義 SQL。
??選擇建議:??
- 如果你的項目有??大量簡單的單表 CRUD 操作??,追求??開發效率??,且需要??分頁、樂觀鎖??等常見功能,??MyBatis-Plus 是絕佳選擇??。
- 如果你的項目??極其復雜??,涉及大量??定制化 SQL、存儲過程、復雜的多表關聯和嵌套查詢??,或者你對 SQL 有??絕對的控制欲??,??原生 MyBatis 可能更合適??(或者結合使用,復雜部分用原生)。
- ??實際項目中,兩者結合使用非常常見:?? 簡單 CRUD 用 MP 的
BaseMapper
和Wrapper
,復雜查詢或存儲過程調用則使用原生 MyBatis 的 XML 或注解方式編寫 SQL。MP 的@SqlParser(filter=true)
可以讓你在同一個 Mapper 中混合使用這兩種方式。