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

MyBatis-Plus基于MyBatis封裝 BaseMapper的流程步驟

 更新時(shí)間:2025年04月03日 08:39:04   作者:Asthenian  
MyBatis-Plus作為 MyBatis 的增強(qiáng)框架,通過 BaseMapper 提供了通用的 CRUD 操作,極大地提升了開發(fā)效率,為了更透徹地理解其封裝機(jī)制,本文將采用鏈路追蹤的思維,從開發(fā)者調(diào)用接口開始,分析其如何基于 MyBatis 完成對(duì) BaseMapper 的封裝,需要的朋友可以參考下

引言

MyBatis-Plus(簡(jiǎn)稱 MP)作為 MyBatis 的增強(qiáng)框架,通過 BaseMapper 提供了通用的 CRUD 操作,極大地提升了開發(fā)效率。為了更透徹地理解其封裝機(jī)制,本文將采用鏈路追蹤的思維,從開發(fā)者調(diào)用接口開始,逐步深入到 MyBatis-Plus 的核心實(shí)現(xiàn),分析其如何基于 MyBatis 完成對(duì) BaseMapper 的封裝。

一、從調(diào)用開始:BaseMapper 的使用場(chǎng)景

假設(shè)我們有一個(gè)簡(jiǎn)單的實(shí)體類 User 和對(duì)應(yīng)的 Mapper 接口:

@TableName("t_user")
public class User {
    @TableId
    private Long id;
    private String name;
    private Integer age;
    // getter 和 setter 省略
}

public interface UserMapper extends BaseMapper<User> {
}

開發(fā)者只需這樣調(diào)用:

UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.selectById(1L);

表面上看,selectByIdBaseMapper 提供的方法,但其背后是如何實(shí)現(xiàn)的呢?讓我們沿著調(diào)用鏈路逐步追蹤。

二、鏈路追蹤:從接口調(diào)用到代理執(zhí)行

1. 獲取 Mapper 代理對(duì)象

當(dāng)調(diào)用 sqlSession.getMapper(UserMapper.class) 時(shí),MyBatis 的 SqlSession 會(huì)委托給 ConfigurationgetMapper 方法:

// MyBatis: org.apache.ibatis.session.Configuration
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    return mapperRegistry.getMapper(type, sqlSession);
}

這里的 mapperRegistry 是 MyBatis 的 MapperRegistry 類,但在 MyBatis-Plus 中被替換為 MybatisMapperRegistry。鏈路進(jìn)入 MyBatis-Plus 的自定義實(shí)現(xiàn):

// MyBatis-Plus: com.baomidou.mybatisplus.core.MybatisMapperRegistry
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
    if (mapperProxyFactory == null) {
        throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
    }
    return mapperProxyFactory.newInstance(sqlSession);
}
  • 關(guān)鍵點(diǎn):MyBatis-Plus 重寫了 MapperRegistry,并在啟動(dòng)時(shí)通過掃描將所有繼承 BaseMapper 的接口注冊(cè)到 knownMappers 中。
  • 代理生成newInstance 方法創(chuàng)建了一個(gè) MapperProxy 對(duì)象,這是 JDK 動(dòng)態(tài)代理的實(shí)現(xiàn)。

2. 方法調(diào)用攔截

當(dāng)調(diào)用 userMapper.selectById(1L) 時(shí),代理對(duì)象 MapperProxyinvoke 方法被觸發(fā):

// MyBatis-Plus: com.baomidou.mybatisplus.core.override.MybatisMapperProxy
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    if (Object.class.equals(method.getDeclaringClass())) {
        return method.invoke(this, args);
    }
    MybatisMapperMethod mapperMethod = cachedMapperMethod(method);
    return mapperMethod.execute(sqlSession, args);
}
  • 鏈路分叉cachedMapperMethod 會(huì)根據(jù)方法簽名緩存并返回一個(gè) MybatisMapperMethod 對(duì)象。
  • 執(zhí)行邏輯execute 方法根據(jù)方法名和參數(shù)決定具體的執(zhí)行路徑。

對(duì)于 selectById,鏈路進(jìn)入 MybatisMapperMethod.execute

// MyBatis-Plus: com.baomidou.mybatisplus.core.override.MybatisMapperMethod
public Object execute(SqlSession sqlSession, Object[] args) {
    if (SqlCommandType.SELECT == command.getType()) {
        if (method.getReturnType().isAssignableFrom(List.class)) {
            return sqlSession.selectList(command.getName(), args);
        }
        return sqlSession.selectOne(command.getName(), args[0]);
    }
    // 其他類型如 INSERT、UPDATE 等略
}
  • 關(guān)鍵點(diǎn)command.getName() 返回的是一個(gè)全局唯一的 SQL ID,例如 com.baomidou.mybatisplus.core.mapper.BaseMapper.selectById。
  • 執(zhí)行 SQL:最終調(diào)用 MyBatis 的 selectOne 方法執(zhí)行查詢。

三、SQL 注入:BaseMapper 方法的實(shí)現(xiàn)來源

問題來了:selectById 的 SQL 是從哪里來的?答案在于 MyBatis-Plus 的 SQL 注入機(jī)制。

1. 啟動(dòng)時(shí)的 SQL 注入

MyBatis-Plus 在 Spring 容器初始化時(shí),通過 MapperScannerConfigurer 掃描 Mapper 接口,并調(diào)用 ISqlInjector 注入通用 SQL:

// MyBatis-Plus: com.baomidou.mybatisplus.core.injector.DefaultSqlInjector
public void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass) {
    List<AbstractMethod> methodList = getMethodList(mapperClass);
    for (AbstractMethod method : methodList) {
        method.inject(builderAssistant, mapperClass);
    }
}
  • 方法列表getMethodList 返回 BaseMapper 中定義的所有方法(如 selectById、insert 等)的實(shí)現(xiàn)類,例如 SelectById。
  • 注入過程:以 SelectById 為例:
// MyBatis-Plus: com.baomidou.mybatisplus.core.injector.methods.SelectById
public void injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
    String sql = String.format("<script>SELECT %s FROM %s WHERE %s = #{id}</script>",
        sqlSelectColumns(), tableInfo.getTableName(), tableInfo.getKeyColumn());
    SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
    addSelectMappedStatement(mapperClass, "selectById", sqlSource, modelClass, tableInfo);
}
  • SQL 生成:根據(jù) TableInfo(通過反射解析實(shí)體類)動(dòng)態(tài)生成 SELECT * FROM t_user WHERE id = #{id}。
  • 注冊(cè):將生成的 MappedStatement 注冊(cè)到 MyBatis 的 Configuration 中。

2. TableInfo 的作用

TableInfo 是 MyBatis-Plus 的核心元數(shù)據(jù)類,通過 TableInfoHelper 在啟動(dòng)時(shí)解析實(shí)體類:

  • @TableName("t_user") → 表名 t_user。
  • @TableId → 主鍵字段 id。
  • 字段映射 → 自動(dòng)推斷 name、age 等列名。

這些信息為 SQL 注入提供了基礎(chǔ)數(shù)據(jù)。

四、鏈路總結(jié):從調(diào)用到執(zhí)行的全流程

  • 開發(fā)者調(diào)用userMapper.selectById(1L)。
  • 代理攔截MybatisMapperProxy.invokeMybatisMapperMethod.execute。
  • SQL 執(zhí)行sqlSession.selectOne → MyBatis 執(zhí)行預(yù)注入的 MappedStatement
  • 結(jié)果映射:MyBatis 將查詢結(jié)果映射為 User 對(duì)象返回。

背后支持:

  • 啟動(dòng)時(shí):掃描 Mapper → 注入通用 SQL → 注冊(cè) MappedStatement
  • 運(yùn)行時(shí):動(dòng)態(tài)代理 → 方法路由 → SQL 執(zhí)行。

五、與 MyBatis 的協(xié)作與增強(qiáng)

  • 復(fù)用 MyBatis:動(dòng)態(tài)代理、SqlSession、結(jié)果映射等核心機(jī)制完全繼承自 MyBatis。
  • 增強(qiáng)點(diǎn)

    SQL 自動(dòng)化:通過 ISqlInjector 注入通用 SQL。

    元數(shù)據(jù)管理TableInfo 實(shí)現(xiàn)實(shí)體與表的自動(dòng)映射。

    條件構(gòu)造Wrapper 擴(kuò)展了動(dòng)態(tài)查詢能力。

六、結(jié)論

MyBatis-Plus 對(duì) BaseMapper 的封裝,是在 MyBatis 動(dòng)態(tài)代理和 SQL 執(zhí)行框架上的巧妙擴(kuò)展。通過啟動(dòng)時(shí)的 SQL 注入和運(yùn)行時(shí)的代理攔截,它實(shí)現(xiàn)了通用 CRUD 的零配置使用。鏈路追蹤顯示,這種設(shè)計(jì)既保留了 MyBatis 的靈活性,又通過自動(dòng)化大幅提升了開發(fā)效率,堪稱對(duì) MyBatis 的“完美補(bǔ)完”。

以上就是MyBatis-Plus基于MyBatis封裝 BaseMapper的流程步驟的詳細(xì)內(nèi)容,更多關(guān)于MyBatis-Plus封裝 BaseMapper的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 詳解MyBatis動(dòng)態(tài)代理機(jī)制

    詳解MyBatis動(dòng)態(tài)代理機(jī)制

    MyBatis的動(dòng)態(tài)代理機(jī)制是其核心特性之一,通過該機(jī)制,開發(fā)者可以專注于定義接口和 SQL 映射,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2026-03-03
  • Spring占位符Placeholder的實(shí)現(xiàn)原理解析

    Spring占位符Placeholder的實(shí)現(xiàn)原理解析

    這篇文章主要介紹了Spring占位符Placeholder的實(shí)現(xiàn)原理,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • 詳解Java設(shè)計(jì)模式之抽象工廠模式

    詳解Java設(shè)計(jì)模式之抽象工廠模式

    設(shè)計(jì)模式是軟件設(shè)計(jì)中的一種常見方法,通過定義一系列通用的解決方案,來解決常見的軟件設(shè)計(jì)問題,其中,抽象工廠模式是一種非常常見的設(shè)計(jì)模式,文中有詳細(xì)的代碼示例供大家參考,感興趣的同學(xué)可以借鑒閱讀
    2023-05-05
  • MyBatisPlus中Join聯(lián)表查詢的項(xiàng)目實(shí)踐

    MyBatisPlus中Join聯(lián)表查詢的項(xiàng)目實(shí)踐

    MyBatis-Plus本身并不直接支持JOIN連表查詢,可以通過自定義SQL或者使用MyBatis的原生XML配置來實(shí)現(xiàn)JOIN連表查詢,本文就來介紹一下MyBatisPlus中Join聯(lián)表查詢的項(xiàng)目實(shí)踐,感興趣的可以了解一下
    2026-04-04
  • 如何基于Idea遠(yuǎn)程調(diào)試tomcat war包及jar包

    如何基于Idea遠(yuǎn)程調(diào)試tomcat war包及jar包

    這篇文章主要介紹了如何基于Idea遠(yuǎn)程調(diào)試tomcat war包及jar包,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-08-08
  • Java界面編程實(shí)現(xiàn)界面跳轉(zhuǎn)

    Java界面編程實(shí)現(xiàn)界面跳轉(zhuǎn)

    這篇文章主要為大家詳細(xì)介紹了Java界面編程實(shí)現(xiàn)界面跳轉(zhuǎn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • Java四舍五入時(shí)保留指定小數(shù)位數(shù)的五種方式

    Java四舍五入時(shí)保留指定小數(shù)位數(shù)的五種方式

    這篇文章主要介紹了Java四舍五入時(shí)保留指定小數(shù)位數(shù)的五種方式,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2020-09-09
  • Java?swing創(chuàng)建一個(gè)窗口的簡(jiǎn)單步驟

    Java?swing創(chuàng)建一個(gè)窗口的簡(jiǎn)單步驟

    這篇文章主要給大家介紹了關(guān)于Java?swing創(chuàng)建一個(gè)窗口的簡(jiǎn)單步驟,Java Swing是Java平臺(tái)下的GUI(Graphical User Interface,圖形用戶界面)工具包,提供了豐富的GUI組件,可以實(shí)現(xiàn)復(fù)雜的圖形界面應(yīng)用程序,需要的朋友可以參考下
    2024-06-06
  • 淺談Tomcat三種運(yùn)行模式

    淺談Tomcat三種運(yùn)行模式

    這篇文章主要介紹了淺談Tomcat三種運(yùn)行模式,小編冒昧將兩篇文章略微整合了一下,有不足的地方,歡迎指出。需要的朋友可以參考。
    2017-10-10
  • java 調(diào)用本地?fù)P聲器的步驟

    java 調(diào)用本地?fù)P聲器的步驟

    博主的畢設(shè)系統(tǒng)在做一個(gè)餐廳的點(diǎn)餐管理系統(tǒng),在進(jìn)行移動(dòng)端頁面開發(fā)的時(shí)候突發(fā)奇想做一個(gè)呼叫功能,因此就有了這篇文章
    2021-05-05

最新評(píng)論

三门峡市| 日照市| 沿河| 徐汇区| 广德县| 长兴县| 通化县| 阳曲县| 澎湖县| 来安县| 烟台市| 平顺县| 赤水市| 施秉县| 科技| 古交市| 保山市| 枣阳市| 庆云县| 通城县| 新绛县| 简阳市| 五常市| 甘谷县| 灵璧县| 尖扎县| 太和县| 姚安县| 昔阳县| 清丰县| 祥云县| 梨树县| 清远市| 泽库县| 大田县| 峨眉山市| 石嘴山市| 永丰县| 毕节市| 新和县| 襄汾县|