欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

引言

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

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

假設(shè)我們有一個簡單的實(shí)體類 User 和對應(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 代理對象

當(dāng)調(diào)用 sqlSession.getMapper(UserMapper.class) 時,MyBatis 的 SqlSession 會委托給 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,并在啟動時通過掃描將所有繼承 BaseMapper 的接口注冊到 knownMappers 中。
  • 代理生成newInstance 方法創(chuàng)建了一個 MapperProxy 對象,這是 JDK 動態(tài)代理的實(shí)現(xiàn)。

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

當(dāng)調(diào)用 userMapper.selectById(1L) 時,代理對象 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 會根據(jù)方法簽名緩存并返回一個 MybatisMapperMethod 對象。
  • 執(zhí)行邏輯execute 方法根據(jù)方法名和參數(shù)決定具體的執(zhí)行路徑。

對于 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() 返回的是一個全局唯一的 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. 啟動時的 SQL 注入

MyBatis-Plus 在 Spring 容器初始化時,通過 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í)體類)動態(tài)生成 SELECT * FROM t_user WHERE id = #{id}。
  • 注冊:將生成的 MappedStatement 注冊到 MyBatis 的 Configuration 中。

2. TableInfo 的作用

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

  • @TableName("t_user") → 表名 t_user
  • @TableId → 主鍵字段 id。
  • 字段映射 → 自動推斷 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 對象返回。

背后支持:

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

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

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

    SQL 自動化:通過 ISqlInjector 注入通用 SQL。

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

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

六、結(jié)論

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

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

相關(guān)文章

  • Java并發(fā)之嵌套管程鎖死詳解

    Java并發(fā)之嵌套管程鎖死詳解

    這篇文章主要介紹了Java并發(fā)之嵌套管程鎖死詳解,涉及嵌套管程鎖死的發(fā)生,實(shí)例等相關(guān)內(nèi)容,具有一定參考價值,需要的朋友可以了解下。
    2017-11-11
  • javaSE基礎(chǔ)java自定義注解原理分析

    javaSE基礎(chǔ)java自定義注解原理分析

    這篇文章主要介紹了javaSE基礎(chǔ)對java自定義注解原理分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多度進(jìn)步,早日升職加薪
    2021-10-10
  • 淺談springboot內(nèi)置tomcat和外部獨(dú)立部署tomcat的區(qū)別

    淺談springboot內(nèi)置tomcat和外部獨(dú)立部署tomcat的區(qū)別

    這篇文章主要介紹了淺談springboot內(nèi)置tomcat和外部獨(dú)立部署tomcat的區(qū)別,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • java使用apache.poi導(dǎo)出word文件的示例代碼

    java使用apache.poi導(dǎo)出word文件的示例代碼

    這篇文章主要介紹了java使用apache.poi導(dǎo)出word文件,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-07-07
  • springcloud如何獲取網(wǎng)關(guān)封裝的頭部信息

    springcloud如何獲取網(wǎng)關(guān)封裝的頭部信息

    這篇文章主要介紹了springcloud獲取網(wǎng)關(guān)封裝的頭部信息,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • Maven編譯Fatal?error?compiling:無效的目標(biāo)發(fā)行版:11問題及解決

    Maven編譯Fatal?error?compiling:無效的目標(biāo)發(fā)行版:11問題及解決

    在Java11中編譯Springboot工程時遇到問題,解決方法是在pom.xml文件中指定Maven的Java編譯器版本,可以使用MavenJava編譯器屬性或插件,在Java9及以后的版本中,也要使用插件并設(shè)置release屬性
    2024-12-12
  • 從java面試題了解你所模糊的數(shù)組

    從java面試題了解你所模糊的數(shù)組

    這篇文章主要介紹了從java面試題了解你所模糊的數(shù)組,數(shù)組用來存儲一系列的數(shù)據(jù)項,其中的每一項具有相同的基本數(shù)據(jù)類型、類或相同的父類。通過使用數(shù)組,可以在很大程度上縮短和簡化程序代碼,從而提高應(yīng)用程序的效率。,需要的朋友可以參考下
    2019-06-06
  • Java運(yùn)行Python腳本的幾種方式小結(jié)

    Java運(yùn)行Python腳本的幾種方式小結(jié)

    在跨語言編程中,有時候我們需要在 Java 應(yīng)用程序中執(zhí)行 Python 腳本,這可能是為了利用 Python 豐富的庫生態(tài)系統(tǒng),或者是為了在已有 Java 系統(tǒng)中集成一些 Python 特有的功能,本文給大家介紹了實(shí)現(xiàn)這幾種目標(biāo)的方法,需要的朋友可以參考下
    2024-12-12
  • java中調(diào)用super的實(shí)例講解

    java中調(diào)用super的實(shí)例講解

    在本篇文章里小編給大家分享了一篇關(guān)于java中調(diào)用super的實(shí)例講解內(nèi)容,有興趣的朋友們可以學(xué)習(xí)下。
    2020-12-12
  • Java看完秒懂版熔斷和降級的關(guān)系

    Java看完秒懂版熔斷和降級的關(guān)系

    這篇文章主要介紹了Java熔斷和降級的關(guān)系,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-09-09

最新評論