当前位置: 首页 > news >正文

mybatis-plus从入门到入土(四):持久层接口之BaseMapper和选装件

大家好,今天继续更新MybatisPlus从入门到入土系列,上一次的持久层接口还没讲完,只讲了IService接口,今天我们继续来讲一下。

BaseMapper

BaseMapper中的方法也比较简单,都是增删改查的基础API,不知道大家还有没有印象,上次在讲IService相关类结构的时候,我们分析了一个CrudRepository,它就是通过成员变量BaseMapper完成了部门能力,当时我还把BaseMapper比喻成引擎(或者发动机)。BaseMapper的相关类结构只有一个父接口MapperMapper接口作为顶层接口,只起到标记的作用,没有定义方法。因此BaseMapper的相关类结构是非常清晰的,这里也不过多赘述了。关于BaseMapper的实现原理,我们计划在后面讲解源码的时候会讲到。

Mapper层选装件

关于Mapper层选装件,其实就是Mapper的扩展功能,虽然MybatisPlus已经提供了BaseMapper这个比较丰富的父类,但是还是有些比较场景化的需求需要定制实现,这就是选装件的意义。在官方文档中描述也可以看出,选装件是需要配合SQL注入器一起使用的。关于SQL注入器后面还会单独说到,这些选装件都位于com.baomidou.mybatisplus.extension.injector.methods,下面我们具体来看下这几个选装件。

在这里插入图片描述
关于这几个选装件的作用,大家可以看下官方文档https://baomidou.com/guides/data-interface/#mapper-%E5%B1%82%E9%80%89%E8%A3%85%E4%BB%B6,我们主要分析下他们的具体实现。还有一点需要补充的是,关于SQL注入器后面会讲到,今天只对这几个选装件做一下剖析。

首先在3.5.12版本中能看到的选装件有5个:AlwaysUpdateSomeColumnByIdInsertBatchSomeColumnLogicDeleteBatchByIdsLogicDeleteByIdWithFillUpsert。其中LogicDeleteBatchByIdsLogicDeleteByIdWithFill官方已标注为过期。

AbstractMethod

首先说下他们都继承的类,就是这个AbstractMethodAbstractMethod作为SQL注入的基础类,它的主要方法是inject方法。

TIPS

这里说一个小技巧啊,当你看源码的时候,仅从类出发不知道入口点是哪个方法,可以先找下类中public的方法,一般需要子类实现的都会标注为protected。

/*** 注入自定义方法*/
public void inject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {this.configuration = builderAssistant.getConfiguration();this.builderAssistant = builderAssistant;this.languageDriver = configuration.getDefaultScriptingLanguageInstance();/* 注入自定义方法 */injectMappedStatement(mapperClass, modelClass, tableInfo);
}

再看下injectMappedStatement方法。injectMappedStatement是一个抽象方法,实现的子类就包括我们提到的那几个选装件。
在这里插入图片描述
我们挑一个看下吧,比如AlwaysUpdateSomeColumnById,看下这个类中的injectMappedStatement是怎么实现的。

@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {SqlMethod sqlMethod = SqlMethod.UPDATE_BY_ID;final String additional = optlockVersion(tableInfo) + tableInfo.getLogicDeleteSql(true, true);String sqlSet = this.filterTableFieldInfo(tableInfo.getFieldList(), getPredicate(),i -> i.getSqlSet(true, ENTITY_DOT), NEWLINE);sqlSet = SqlScriptUtils.convertSet(sqlSet);String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), sqlSet,tableInfo.getKeyColumn(), ENTITY_DOT + tableInfo.getKeyProperty(), additional);SqlSource sqlSource = super.createSqlSource(configuration, sql, modelClass);return addUpdateMappedStatement(mapperClass, modelClass, methodName, sqlSource);
}

这个方法的主要作用就是创建一个updateMappeedStatement,加入到Mybatis的全局配置中。其中sqlMethod是SQL语句的模板,拿到这个UPDATE_BY_ID的sql语句模板后,下面就是把模板填充成正常的SQL语句,就涉及到需要set的字段啊,乐观锁之类的。当这些信息都拼接完了,把它放入一个SqlSource的对象中,然后根据这个SqlSource对象生成MappedStatement。整个方法逻辑看起来比较清晰,但是有几点需要补充一下,如果没有这些前置知识,这块可能还是比较蒙。

  • SqlMethod长什么样?

    我们看下这个SqlMethod究竟长什么样,其实就是一个String模板,也就是我们经常用的String.format的定义形式。而<script>标签是Mybatis提供的,该标签主要是用来拼接SQL脚本的。

    UPDATE_BY_ID("updateById", "根据ID 选择修改数据", "<script>\nUPDATE %s %s WHERE %s=#{%s} %s\n</script>")
    
  • MappedStatement类是干什么的?

    这个类是Mybatis框架中的重要类,他对应的就是xml文件中的一个个标签包起来的元素,比如<insert>元素,<select>元素。这里简述一下Mybatis的原理啊,Mybatis框架启动的时候会去解析xml文件,将里面的一个个标签实例化成一个个MappedStatement对象。最终这些解析出来的MappedStatement都会放入Configuration类,关于这一块大家可以看下org.apache.ibatis.builder.xml.XMLConfigBuilder#parseConfiguration

  • SqlSource类是干什么的?

    其实从类的注释中,我们基本上也能明白是什么意思了,就是在<insert>标签中的插入语句,包在<select>语句中的查询语句等,这个SqlSource类的作用就是这些SQL语句的容器。

    /*** Represents the content of a mapped statement read from an XML file or an annotation. It creates the SQL that will be passed to the database out of the input parameter received from the user.* 表示从 XML 文件或注释读取的映射语句的内容。它创建将从用户收到的输入参数传递到数据库的 SQL。* @author Clinton Begin*/
    public interface SqlSource {BoundSql getBoundSql(Object parameterObject);}
    

经过上面的几个问题,大家应该知道了这几个类其实就是定义了几个不同的MappedStatement方法,然后注入到Configuration类中。相比于传统的在xml中定义,或者在mapper方法上面注解定义,这些都是自己注入的,关于怎么注入的,在哪注入的,这块就是SQL注入器的内容了,我们后面会讲到。

好了,今天先讲到这里。这里需要说明一下,官方文档中持久化接口涉及的东西很多,我们可能得分多次讲解,我最初规划的是一篇讲完的,但我还是觉得一次讲太多会很长,也不太好消化,就篇幅短一些吧。下周见,拜拜。

先讲到这里。这里需要说明一下,官方文档中持久化接口涉及的东西很多,我们可能得分多次讲解,我最初规划的是一篇讲完的,但我还是觉得一次讲太多会很长,也不太好消化,就篇幅短一些吧。下周见,拜拜。

http://www.dtcms.com/a/313182.html

相关文章:

  • PHP现代化全栈开发:前后端分离与API架构实践
  • uni-app学习笔记01-项目初始化及相关文件
  • Go语言常量
  • 11.消息队列
  • 计算机视觉CS231n学习(2)
  • 从马武寨穿越关山
  • ICCV 2025 | EPD-Solver:西湖大学发布并行加速扩散采样算法
  • p5.js 用 beginGeometry () 和 endGeometry () 打造自定义 3D 模型
  • 控制建模matlab练习06:比例积分控制-②PI控制器
  • 达梦数据库联机备份和脱机备份的区别
  • Centos7 安装Python3.11
  • 【Linux系统编程】进程信号
  • leecode2958 最多K个重复元素的最长子数组
  • 解决飞书文档中PDF文档禁止下载的问题
  • 提升工作效率的利器:Qwen3 大语言模型
  • Python 程序设计讲义(60):Python 的函数——递归函数
  • 出现OOM怎么排查
  • 研报复现|史蒂夫·路佛价值选股法则
  • linux ollama模型缓存位置变更
  • 音视频学习(四十九):音频有损压缩
  • 机器学习之决策树(二)
  • 解决PyCharm的Terminal终端conda环境默认为base的问题
  • 【硬件-笔试面试题】硬件/电子工程师,笔试面试题-57,(知识点:电感的选型,电感参数,电感量,饱和电流,直流电阻,自谐振频率)
  • 可视化AI应用构建工具(Dyad)
  • 【内容规范】关于标题中【】标记的使用说明
  • 2.0 vue工程项目的创建
  • TableCurve 3D:自动化曲面拟合与方程发现
  • Steam饥荒联机版多人服务器搭建全解析 -- 阿里云Linux系统构建云服务器
  • Flutter dart控制流程
  • Shell脚本-变量的定义规则