最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring boot 4 搞懂MyBatis-Plus的用法解析

 更新時間:2026年01月10日 10:10:36   投稿:mrr  
MyBatis-Plus是MyBatis的增強工具,提供了CRUD操作和自動填充等功能,通過繼承BaseMapper接口,可以快速實現(xiàn)數(shù)據(jù)庫操作,MyBatis-Plus提供了多種插件,如分頁、樂觀鎖、多租戶等,以增強系統(tǒng)的功能和性能,本文介紹Spring boot 4 搞懂MyBatis-Plus的用法,感興趣的朋友一起看看吧

MyBatis-Plus 是一個 MyBatis 的增強工具,在 MyBatis 的基礎(chǔ)上只做增強不做改變,為簡化開發(fā)、提高效率而生

官方地址:
git源碼
文檔

Spring boot 4如何集成

增加依賴

Add MyBatis-Plus dependency

<mybatisplus.version>3.5.15</mybatisplus.version>
		<dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-spring-boot4-starter</artifactId>
            <version>${mybatisplus.version}</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-jsqlparser</artifactId>
            <version>${mybatisplus.version}</version>
        </dependency>

配置

@Configuration
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        // 數(shù)據(jù)權(quán)限
        mybatisPlusInterceptor.addInnerInterceptor(new DataFilterInterceptor());
        // 分頁插件
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        // 樂觀鎖
        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        // 防止全表更新與刪除
        mybatisPlusInterceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
        return mybatisPlusInterceptor;
    }
}

基礎(chǔ)特性

  1. “零SQL” CRUD
    • 核心點:業(yè)務(wù)模塊的Mapper 接口繼承 BaseMapper<T>,即可擁有 insert、selectById、updateById、deleteBatchIds 等 17 個常用方法。
    • Service CRUD:除了 Mapper 層,MP 還提供了 IServiceServiceImpl,封裝了更多的業(yè)務(wù)邏輯方法(如 saveBatch 批量插入)。
    • 提供SqlHelper工具類實現(xiàn)批量寫入或更新操作
  2. 條件構(gòu)造器(Wrapper)
    • 三板斧QueryWrapper(用于查詢,支持lambda避免字段名寫錯)、UpdateWrapper(用于更新,支持鏈式設(shè)置 set 值)。
    • Lambda 表達式:推薦使用 LambdaQueryWrapper,利用方法引用(如 User::getName)來指定字段,編譯期檢查,防止 SQL 拼寫錯誤。
  3. 常用注解
    • @TableName:指定表名(如果類名與表名不一致)。
    • @TableId:指定主鍵策略(如 IdType.AUTO 自增,IdType.ASSIGN_ID 雪花算法)。
    • @TableField:填充字段(如創(chuàng)建時間、更新時間自動填充 FieldFill.INSERT_UPDATE),或者邏輯刪除字段 @TableLogic

增強功能

  1. 自動填充
    • 自動填充:實現(xiàn) MetaObjectHandler 接口,重寫 insertFillupdateFill 方法,統(tǒng)一處理 create_time、update_time 等字段。
  • 邏輯刪除:配置后,delete 語句會自動轉(zhuǎn)化為 UPDATE 語句(設(shè)置刪除標記),查詢時自動追加 WHERE deleted = 0 條件。 【在實體類中,對應(yīng)數(shù)據(jù)庫表的邏輯刪除字段上添加 @TableLogic 注解】
    • 插入:邏輯刪除字段的值不受限制。
    • 查找:自動添加條件,過濾掉標記為已刪除的記錄。
    • 更新:防止更新已刪除的記錄。
    • 刪除:將刪除操作轉(zhuǎn)換為更新操作,標記記錄為已刪除
  • 自定義ID生成器
    • IdentifierGenerator主要用于生成數(shù)據(jù)庫表的主鍵ID
    • KeyGenerator是MyBatis框架中的一個接口,用于在執(zhí)行SQL語句時生成鍵值,通常用于生成自增主鍵或者在執(zhí)行INSERT語句后獲取新生成的ID
    • MyBatis-Plus 內(nèi)置支持多種數(shù)據(jù)庫的主鍵生成策略,如:
      • H2KeyGenerator
      • OracleKeyGenerator
      • PostgreKeyGenerator
  • 多數(shù)據(jù)源支持:詳細使用參見https://github.com/baomidou/dynamic-datasource
    • Spring Boot 1.5.x ~ 2.x.x 使用 dynamic-datasource-spring-boot-starter,支持 JDK 8 及以上版本
    • Spring Boot 3.x.x 使用 dynamic-datasource-spring-boot3-starter要求 JDK 17 及以上
    • Spring Boot 4.x.x 使用 dynamic-datasource-spring-boot4-starter,要求 JDK 17 及以上

插件機制

常用插件

  1. 分頁插件(PaginationInnerInterceptor)
    • 原理:MP 的分頁不是內(nèi)存分頁,而是物理分頁。它通過 MyBatis 的攔截器(Interceptor)機制,在 SQL 執(zhí)行前重寫 SQL(如加上 LIMIT)。
    • 使用:配置 MybatisPlusInterceptor,注入 PaginationInnerInterceptor。代碼中使用 Page<T> 對象接收結(jié)果。
  2. 樂觀鎖插件OptimisticLockerInnerInterceptor
    1. 讀取記錄時,獲取當前的版本號(version)。
    2. 在更新記錄時,將這個版本號一同傳遞。
    3. 執(zhí)行更新操作時,設(shè)置 version = newVersion 的條件為 version = oldVersion。
    4. 如果版本號不匹配,則更新失敗。
  3. 多租戶插件 TenantLineInnerInterceptor
    1. 是 MyBatis-Plus 提供的一個插件,用于實現(xiàn)多租戶的數(shù)據(jù)隔離。通過這個插件,可以確保每個租戶只能訪問自己的數(shù)據(jù),從而實現(xiàn)數(shù)據(jù)的安全隔離
    2. 默認插入 SQL 是需要判斷租戶條件,因此需要配合自動填充字段功能填充租戶字段,否則租戶字段不會自動保存到數(shù)據(jù)庫
  4. 非法SQL攔截插件IllegalSQLInnerInterceptor
    • 用于攔截和檢查非法SQL語句。該插件旨在幫助開發(fā)者在SQL執(zhí)行前發(fā)現(xiàn)并解決潛在的安全問題,如全表更新、刪除操作,以及對索引的檢查等
  5. 防全表更新與刪除插件BlockAttackInnerInterceptor
    1. 專門用于防止惡意的全表更新和刪除操作。該插件通過攔截 updatedelete 語句,確保這些操作不會無意中影響到整個數(shù)據(jù)表,從而保護數(shù)據(jù)的完整性和安全性

執(zhí)行流程

MyBatis-Plus(MP)插件的執(zhí)行流程,本質(zhì)上是基于 MyBatis 的插件(Plugin)機制實現(xiàn)的。MP 利用這一機制,在 MyBatis 的核心執(zhí)行流程中“插入”自己的邏輯,從而實現(xiàn)分頁、性能分析、SQL 注入防護等功能。

MybatisPlusInterceptor 是“包工頭”,它實現(xiàn)了 MyBatis 的接口并攔下所有活;而 List<InnerInterceptor>是“工人”,實現(xiàn)具體的功能

組件層級類/接口名稱職責(zé)實現(xiàn)關(guān)系
頂層門面MybatisPlusInterceptor實現(xiàn) MyBatis 原生 Interceptor,作為唯一入口,管理插件列表。實現(xiàn)
org.apache.ibatis.
plugin.Interceptor
插件容器List<InnerInterceptor>存儲具體的增強邏輯(如分頁、樂觀鎖),由頂層門面調(diào)用。內(nèi)部持有
具體邏輯PaginationInnerInterceptor
實現(xiàn)具體的業(yè)務(wù)邏輯(如重寫 SQL、計算耗時)。實現(xiàn)
InnerInterceptor

如何自定義SQL

通過如下注解,可以實現(xiàn)自定義SQL

  • @Select: 查詢
  • @Insert: 插入
  • @Update: 更新
  • @Delete: 刪除
@Mapper
public interface UserMapper extends BaseMapper<User> {
    // 簡單查詢
    @Select("SELECT * FROM user WHERE email = #{email}")
    User selectByEmail(@Param("email") String email);
    // 復(fù)雜一點的條件查詢
    @Select("SELECT * FROM user WHERE status = #{status} AND age > #{minAge}")
    List<User> selectByStatusAndAge(@Param("status") Integer status, @Param("minAge") Integer minAge);
}

mybatis知識

# {}和${}的區(qū)別

  • #{}:是預(yù)編譯處理(PreparedStatement)。MyBatis 會將它替換為 ?,能有效防止 SQL 注入
  • ${}:是字符串替換。直接將變量拼接到 SQL 中,存在注入風(fēng)險,通常用于傳入數(shù)據(jù)庫表名或排序字段(ORDER BY

MyBatis 的一級緩存和二級緩存

  • 一級緩存: 作用域為 SqlSession。在同一個會話中,相同的查詢不再查數(shù)據(jù)庫。默認開啟。
  • 二級緩存: 作用域為 Namespace(多個會話間共享)。需要手動開啟,且實體類必須實現(xiàn)序列化接口。
  • 失效場景: 任何的 INSERT, UPDATE, DELETE 操作都會刷新緩存

實體類屬性名和表中字段名不一致怎么辦?

  1. 在 SQL 語句中使用別名(AS)。
  2. 使用 ResultMap 進行映射(最常用)。
  3. 開啟駝峰命名自動轉(zhuǎn)換配置(mapUnderscoreToCamelCase

Mybatis的緩存機制

一級緩存建議保持默認(開啟),而二級緩存通常不建議開啟(默認也是關(guān)閉的),尤其是在復(fù)雜的業(yè)務(wù)或分布式系統(tǒng)中

一級緩存

一級緩存的實現(xiàn)參見:BaseExecutorPerpetualCache

  • 一級緩存的生命周期由 Executor(執(zhí)行器)管理。在 BaseExecutor(所有執(zhí)行器的基類)中,定義了本地緩存對象
  • SqlSession 每次創(chuàng)建都會生成一個新的 Executor,所以一級緩存是線程隔離的【參見DefaultSqlSessionFactory】

二級緩存

二級緩存的實現(xiàn)參見:CachingExecutorSynchronizedCache
當開啟二級緩存后,MyBatis 會使用 CachingExecutor 包裝原來的 Executor

裝飾器模式: 二級緩存的實現(xiàn)非常優(yōu)雅,PerpetualCache 是基礎(chǔ),通過 SynchronizedCache(同步)、LoggingCache(日志)、ScheduledCache(定時)、SerializedCache(序列化)、LruCache(回收策略)等裝飾器層層包裝,組合出最終需要的功能

特性一級緩存 (Local)二級緩存 (Global)
作用范圍單個 SqlSession 內(nèi)同一個 Mapper 命名空間內(nèi)
數(shù)據(jù)共享獨享,不跨會話共享,跨 SqlSession
默認狀態(tài)開啟關(guān)閉 (需手動配置)
生命周期伴隨 SqlSession 的創(chuàng)建與關(guān)閉伴隨 SqlSessionFactory 的生命周期
清空時機增刪改操作、close()、commit()對應(yīng) Mapper 的增刪改操作、commit()

是否開啟

緩存類型建議配置理由適用場景
一級緩存開啟 (默認)安全、自動管理、提升單次會話性能所有場景(無需干預(yù))
二級緩存關(guān)閉 (默認)避免臟讀、避免分布式不一致復(fù)雜業(yè)務(wù)、分布式系統(tǒng)
二級緩存開啟 (需評估)需處理好序列化和跨表失效問題單機應(yīng)用、數(shù)據(jù)字典、純讀場景

一句話建議: 用好一級緩存,忘掉二級緩存,用 Redis 來做全局緩存

加載流程

MapperImpl方法調(diào)用過程

  1. 代理攔截(MybatisMapperProxy)
    • MybatisMapperProxy 是在 Spring 容器進行依賴注入(@Autowired)時,由 MapperProxyFactory 調(diào)用 getObject 方法實例化的
  2. 命令執(zhí)行(MapperMethod):
    • MybatisMapperProxy 會拿到一個 MapperMethod 實例。
    • 調(diào)用 mapperMethod.execute(sqlSession, args)。
    • 此時,控制權(quán)從 “代理層” 轉(zhuǎn)移到了 “命令層”
  3. SQL 執(zhí)行(SqlSession/Executor):
    • MapperMethod 內(nèi)部會根據(jù) SQL 類型,調(diào)用 sqlSession.selectOne()insert() 等方法。
    • 最終由 Executor 去 JDBC 層面執(zhí)行 SQL
public class MapperRegistry {
    private final Configuration config;
    private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new ConcurrentHashMap();

    public MapperRegistry(Configuration config) {
        this.config = config;
    }

    public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
        MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type);
        if (mapperProxyFactory == null) {
            throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
        } else {
            try {
                return (T)mapperProxyFactory.newInstance(sqlSession);
            } catch (Exception e) {
                throw new BindingException("Error getting mapper instance. Cause: " + e, e);
            }
        }
    }

Spring boot啟動時初始化過程

  1. SqlSessionFactoryp初始化
    • MybatisAutoConfiguration -> MybatisSqlSessionFactoryBean ->SqlSessionFactory
  2. Mapper 注冊與掃描
    • AutoConfiguredMapperScannerRegistrar->AutoConfiguredMapperScannerRegistrar->MapperScannerConfigurer ->ClassPathMapperScanner ->ClassPathBeanDefinitionScanner->MapperFactoryBean
  3. MybatisMapperProxy 實例化
    1. 獲取 Mapper Bean
      • 當 Spring 容器嘗試填充 @Autowired private UserMapper userMapper; 時。
      • 容器發(fā)現(xiàn)這是一個 FactoryBean,于是調(diào)用 MapperFactoryBean.getObject()。
    2. 獲取 SqlSession
      • MapperFactoryBean.getObject() 內(nèi)部會調(diào)用 this.getSqlSession().getMapper(this.mapperInterface);。
    3. 最終實例化 (核心點)
      • sqlSession.getMapper() 會委托給 (T)this.getConfiguration().getMapper(type, this);。
      • Configuration 持有一個 this.mapperRegistry.getMapper(type, sqlSession)(注冊中心)。
      • MapperRegistry 里存著 Class -> MapperProxyFactory 的映射
public class MapperRegistry {
    private final Configuration config;
    private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new ConcurrentHashMap();
    public MapperRegistry(Configuration config) {
        this.config = config;
    }
    public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
        MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type);
        if (mapperProxyFactory == null) {
            throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
        } else {
            try {
                return (T)mapperProxyFactory.newInstance(sqlSession);
            } catch (Exception e) {
                throw new BindingException("Error getting mapper instance. Cause: " + e, e);
            }
        }
    }

到此這篇關(guān)于Spring boot 4 搞懂MyBatis-Plus的用法解析的文章就介紹到這了,更多相關(guān)Spring boot mybatis-plus用法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java設(shè)計模式之備忘錄模式_動力節(jié)點Java學(xué)院

    Java設(shè)計模式之備忘錄模式_動力節(jié)點Java學(xué)院

    我們在編程的時候,經(jīng)常需要保存對象的中間狀態(tài),當需要的時候,可以恢復(fù)到這個狀態(tài)。接下來通過本文給大家分享java設(shè)計模式之備忘錄模式,感興趣的的朋友一起看看吧
    2017-08-08
  • 如何調(diào)試報表插件

    如何調(diào)試報表插件

    在項目開發(fā)過程中插件調(diào)試非常的麻煩,需要修改里面的代碼,編譯出class,需要重新打包插件。然后把之前的刪除,重新安裝最新的。調(diào)試過程比較繁瑣,而且不能調(diào)試,十分的不方便,這篇文章主要介紹的是調(diào)試報表插件的方法,需要的朋友可以參考下
    2015-07-07
  • Java設(shè)計模式之代理模式

    Java設(shè)計模式之代理模式

    這篇文章介紹了Java設(shè)計模式之代理模式,文中通過示例代碼介紹的非常詳細。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-09-09
  • 避免Java內(nèi)存泄漏的10個黃金法則詳細指南

    避免Java內(nèi)存泄漏的10個黃金法則詳細指南

    在Java開發(fā)領(lǐng)域,內(nèi)存泄漏是一個經(jīng)久不衰的話題,也是導(dǎo)致應(yīng)用程序性能下降、崩潰甚至系統(tǒng)癱瘓的常見原因,下面我們就來看看避免Java內(nèi)存泄漏的10個黃金法則吧
    2025-07-07
  • SpringMVC請求/響應(yīng)亂碼問題解決方案解析

    SpringMVC請求/響應(yīng)亂碼問題解決方案解析

    這篇文章主要介紹了SpringMVC請求/響應(yīng)亂碼問題解決方案解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-12-12
  • springboot RESTful以及參數(shù)注解的使用方式

    springboot RESTful以及參數(shù)注解的使用方式

    這篇文章主要介紹了springboot RESTful以及參數(shù)注解的使用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • MyBatis?連接緩慢問題排查與解決實戰(zhàn)技巧

    MyBatis?連接緩慢問題排查與解決實戰(zhàn)技巧

    文章介紹了在維護一個老項目時遇到的MyBatis連接緩慢問題的排查過程和解決方案,本文分階段給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧
    2025-12-12
  • java編程實現(xiàn)并查集的路徑壓縮代碼詳解

    java編程實現(xiàn)并查集的路徑壓縮代碼詳解

    這篇文章主要介紹了java編程實現(xiàn)并查集的路徑壓縮代碼詳解,具有一定借鑒價值,需要的朋友可以參考。
    2017-11-11
  • 詳解JAVA使用Comparator接口實現(xiàn)自定義排序

    詳解JAVA使用Comparator接口實現(xiàn)自定義排序

    這篇文章主要介紹了JAVA使用Comparator接口實現(xiàn)自定義排序,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • Spring Boot全局異常處理機制中DispatcherServlet的處理流程和作用

    Spring Boot全局異常處理機制中DispatcherServlet的處理流程和作用

    本文深入解析Spring Boot全局異常處理機制,重點剖析DispatcherServlet的核心作用及其異常處理流程,詳細介紹了HandlerExceptionResolver接口及其三個默認實現(xiàn)類的執(zhí)行順序和工作原理,通過源碼分析,展示了Spring MVC如何將異常轉(zhuǎn)換為響應(yīng)
    2026-01-01

最新評論

武乡县| 会同县| 禹州市| 交城县| 安福县| 华安县| 常山县| 荣成市| 苏尼特右旗| 中江县| 峨山| 扎兰屯市| 明光市| 洪湖市| 虹口区| 城步| 南投市| 乌恰县| 闽清县| 许昌市| 杭州市| 邳州市| 三都| 江阴市| 萨迦县| 木里| 淮滨县| 内乡县| 广元市| 喀喇沁旗| 思茅市| 通河县| 新巴尔虎左旗| 五常市| 安乡县| 宁河县| 西安市| 博客| 闽清县| 宜阳县| 织金县|