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

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

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

MyBatis-Plus 是一個(gè) MyBatis 的增強(qiáng)工具,在 MyBatis 的基礎(chǔ)上只做增強(qiáng)不做改變,為簡(jiǎn)化開發(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
    • 核心點(diǎn):業(yè)務(wù)模塊的Mapper 接口繼承 BaseMapper<T>,即可擁有 insert、selectById、updateByIddeleteBatchIds 等 17 個(gè)常用方法。
    • Service CRUD:除了 Mapper 層,MP 還提供了 IServiceServiceImpl,封裝了更多的業(yè)務(wù)邏輯方法(如 saveBatch 批量插入)。
    • 提供SqlHelper工具類實(shí)現(xiàn)批量寫入或更新操作
  2. 條件構(gòu)造器(Wrapper)
    • 三板斧QueryWrapper(用于查詢,支持lambda避免字段名寫錯(cuò))、UpdateWrapper(用于更新,支持鏈?zhǔn)皆O(shè)置 set 值)。
    • Lambda 表達(dá)式:推薦使用 LambdaQueryWrapper,利用方法引用(如 User::getName)來指定字段,編譯期檢查,防止 SQL 拼寫錯(cuò)誤。
  3. 常用注解
    • @TableName:指定表名(如果類名與表名不一致)。
    • @TableId:指定主鍵策略(如 IdType.AUTO 自增,IdType.ASSIGN_ID 雪花算法)。
    • @TableField:填充字段(如創(chuàng)建時(shí)間、更新時(shí)間自動(dòng)填充 FieldFill.INSERT_UPDATE),或者邏輯刪除字段 @TableLogic

增強(qiáng)功能

  1. 自動(dòng)填充
    • 自動(dòng)填充:實(shí)現(xiàn) MetaObjectHandler 接口,重寫 insertFillupdateFill 方法,統(tǒng)一處理 create_timeupdate_time 等字段。
  • 邏輯刪除:配置后,delete 語句會(huì)自動(dòng)轉(zhuǎn)化為 UPDATE 語句(設(shè)置刪除標(biāo)記),查詢時(shí)自動(dòng)追加 WHERE deleted = 0 條件。 【在實(shí)體類中,對(duì)應(yīng)數(shù)據(jù)庫(kù)表的邏輯刪除字段上添加 @TableLogic 注解】
    • 插入:邏輯刪除字段的值不受限制。
    • 查找:自動(dòng)添加條件,過濾掉標(biāo)記為已刪除的記錄。
    • 更新:防止更新已刪除的記錄。
    • 刪除:將刪除操作轉(zhuǎn)換為更新操作,標(biāo)記記錄為已刪除
  • 自定義ID生成器
    • IdentifierGenerator主要用于生成數(shù)據(jù)庫(kù)表的主鍵ID
    • KeyGenerator是MyBatis框架中的一個(gè)接口,用于在執(zhí)行SQL語句時(shí)生成鍵值,通常用于生成自增主鍵或者在執(zhí)行INSERT語句后獲取新生成的ID
    • MyBatis-Plus 內(nèi)置支持多種數(shù)據(jù)庫(kù)的主鍵生成策略,如:
      • H2KeyGenerator
      • OracleKeyGenerator
      • PostgreKeyGenerator
  • 多數(shù)據(jù)源支持:詳細(xì)使用參見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 及以上

插件機(jī)制

常用插件

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

執(zhí)行流程

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

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

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

如何自定義SQL

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

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

mybatis知識(shí)

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

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

MyBatis 的一級(jí)緩存和二級(jí)緩存

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

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

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

Mybatis的緩存機(jī)制

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

一級(jí)緩存

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

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

二級(jí)緩存

二級(jí)緩存的實(shí)現(xiàn)參見:CachingExecutor、SynchronizedCache
當(dāng)開啟二級(jí)緩存后,MyBatis 會(huì)使用 CachingExecutor 包裝原來的 Executor

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

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

是否開啟

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

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

加載流程

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

  1. 代理攔截(MybatisMapperProxy)
    • MybatisMapperProxy 是在 Spring 容器進(jìn)行依賴注入(@Autowired)時(shí),由 MapperProxyFactory 調(diào)用 getObject 方法實(shí)例化的
  2. 命令執(zhí)行(MapperMethod):
    • MybatisMapperProxy 會(huì)拿到一個(gè) MapperMethod 實(shí)例。
    • 調(diào)用 mapperMethod.execute(sqlSession, args)。
    • 此時(shí),控制權(quán)從 “代理層” 轉(zhuǎn)移到了 “命令層”
  3. SQL 執(zhí)行(SqlSession/Executor):
    • MapperMethod 內(nèi)部會(huì)根據(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啟動(dòng)時(shí)初始化過程

  1. SqlSessionFactoryp初始化
    • MybatisAutoConfiguration -> MybatisSqlSessionFactoryBean ->SqlSessionFactory
  2. Mapper 注冊(cè)與掃描
    • AutoConfiguredMapperScannerRegistrar->AutoConfiguredMapperScannerRegistrar->MapperScannerConfigurer ->ClassPathMapperScanner ->ClassPathBeanDefinitionScanner->MapperFactoryBean
  3. MybatisMapperProxy 實(shí)例化
    1. 獲取 Mapper Bean
      • 當(dāng) Spring 容器嘗試填充 @Autowired private UserMapper userMapper; 時(shí)。
      • 容器發(fā)現(xiàn)這是一個(gè) FactoryBean,于是調(diào)用 MapperFactoryBean.getObject()。
    2. 獲取 SqlSession
      • MapperFactoryBean.getObject() 內(nèi)部會(huì)調(diào)用 this.getSqlSession().getMapper(this.mapperInterface);。
    3. 最終實(shí)例化 (核心點(diǎn))
      • sqlSession.getMapper() 會(huì)委托給 (T)this.getConfiguration().getMapper(type, this);。
      • Configuration 持有一個(gè) this.mapperRegistry.getMapper(type, sqlSession)(注冊(cè)中心)。
      • 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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java設(shè)計(jì)模式之備忘錄模式_動(dòng)力節(jié)點(diǎn)Java學(xué)院

    Java設(shè)計(jì)模式之備忘錄模式_動(dòng)力節(jié)點(diǎn)Java學(xué)院

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

最新評(píng)論

吴忠市| 吴桥县| 甘孜县| 巩留县| 察雅县| 泗水县| 佛学| 鄂尔多斯市| 津市市| 宝应县| 宁津县| 大埔县| 五河县| 泸水县| 汉中市| 桓仁| 综艺| 普陀区| 柘城县| 商水县| 胶州市| 东山县| 明溪县| 利川市| 呼和浩特市| 青浦区| 台东县| 太白县| 东阿县| 伽师县| 五莲县| 黑山县| 普安县| 湖口县| 靖远县| 准格尔旗| 吕梁市| 策勒县| 即墨市| 千阳县| 宁化县|