深入理解 MyBatis-Plus 的 `BaseMapper`

在使用 MyBatis-Plus(简称 MP)时,开发者几乎一定会接触到 BaseMapper 接口。它是 MP 的核心功能之一,提供了单表的基础 CRUD 操作,极大地减少了样板代码的编写工作。本文将详细介绍 BaseMapper 的作用、常用方法、源码解析以及最佳实践。


1. BaseMapper 简介

BaseMapper<T> 是 MyBatis-Plus 提供的一个 通用 Mapper 接口 ,泛型参数 T 指定实体类类型。

它的设计初衷是:让开发者无需编写 XML 或额外的 SQL,即可直接使用基础的 增删改查方法

定义位置

java 复制代码
package com.baomidou.mybatisplus.core.mapper;

public interface BaseMapper<T> extends Mapper<T> {
    // 内置了丰富的 CRUD 方法
}

只要你的 Mapper 接口继承了 BaseMapper<T>,并指定了对应的实体类,就能直接调用这些 CRUD 方法。例如:

java 复制代码
@Mapper
public interface UserMapper extends BaseMapper<User> {
}

2. 常用方法一览

BaseMapper 内置了近 20 个常用方法,主要涵盖了 增、删、改、查

(1)插入

java 复制代码
int insert(T entity);
  • 功能:插入一条记录
  • 特点:只插入非 null 字段,支持自增主键回填

(2)删除

java 复制代码
int deleteById(Serializable id);
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
int deleteBatchIds(@Param(Constants.COLL) Collection<? extends Serializable> idList);
  • deleteById:根据主键删除
  • deleteBatchIds:批量删除
  • deleteByMap :通过 Map<列名, 值> 删除
  • delete(Wrapper):条件删除(支持 LambdaQueryWrapper)

(3)更新

java 复制代码
int updateById(@Param(Constants.ENTITY) T entity);
int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);
  • updateById:根据主键更新,null 值字段会被更新为 null
  • update :条件更新,配合 UpdateWrapper 使用

(4)查询

java 复制代码
T selectById(Serializable id);
List<T> selectBatchIds(@Param(Constants.COLL) Collection<? extends Serializable> idList);
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
  • 单条查询selectById, selectOne
  • 批量查询selectBatchIds, selectList
  • 分页查询selectPage, selectMapsPage
  • 统计selectCount
  • Map 查询 :返回 Map<String, Object>,适合动态表格场景

3. 使用示例

假设我们有一个 User 实体类:

java 复制代码
@Data
@TableName("user")
public class User {
    private Long id;
    private String name;
    private Integer age;
}

对应的 UserMapper

java 复制代码
@Mapper
public interface UserMapper extends BaseMapper<User> {
}

插入

java 复制代码
User user = new User();
user.setName("张三");
user.setAge(20);
userMapper.insert(user); // 返回插入条数

删除

java 复制代码
userMapper.deleteById(1L);
userMapper.deleteBatchIds(Arrays.asList(1L, 2L, 3L));
userMapper.delete(new QueryWrapper<User>().eq("age", 20));

更新

java 复制代码
User user = userMapper.selectById(1L);
user.setAge(25);
userMapper.updateById(user);

userMapper.update(new User(), new UpdateWrapper<User>().set("age", 30).eq("name", "张三"));

查询

java 复制代码
User user = userMapper.selectById(1L);

List<User> users = userMapper.selectList(new QueryWrapper<User>().ge("age", 18));

Page<User> page = new Page<>(1, 10);
IPage<User> userPage = userMapper.selectPage(page, new QueryWrapper<User>().orderByDesc("id"));

4. 源码解析

BaseMapper 的方法本质上并没有具体实现,而是由 MyBatis-Plus 内置的 SQL 注入器 生成。

  • 默认使用 DefaultSqlInjector
  • 会自动为每个方法拼接对应 SQL
  • 所有方法底层最终都会映射到 XML 或内置 SQL 语句

举例:insert(T entity) 对应的 SQL 类似:

sql 复制代码
INSERT INTO user (id, name, age) VALUES (#{id}, #{name}, #{age})

5. 使用注意事项

  1. 批量操作性能

    • insert 是逐条执行,不是批量插入
    • 建议使用 saveBatch(来自 IService)或自定义 SQL 提升性能
  2. 空值更新

    • updateById 会将 null 字段更新为 null
    • 如果想忽略 null 值,可以使用 UpdateWrapper.set()
  3. 多表查询

    • BaseMapper 仅支持单表操作
    • 多表需要写自定义 SQL 或使用 @Select 注解
  4. Wrapper 灵活性

    • 推荐使用 LambdaQueryWrapper / LambdaUpdateWrapper 避免硬编码列名

    • 例如:

      java 复制代码
      new LambdaQueryWrapper<User>().eq(User::getName, "张三");

6. 总结

  • BaseMapper<T> 是 MyBatis-Plus 提供的核心接口
  • 内置丰富的 CRUD 方法,省去了大量模板代码
  • 搭配 Wrapper 可实现灵活查询
  • 局限性:仅支持单表,复杂场景需自定义 SQL
相关推荐
杨杨杨大侠7 小时前
第6章:高级特性与性能优化
java·github·eventbus
Dcs7 小时前
代码评审还能更好!
java
ITKEY_7 小时前
flutter日期选择国际化支持
开发语言·javascript·flutter
刃神太酷啦8 小时前
C++ 异常处理机制:从基础到实践的全面解析----《Hello C++ Wrold!》(20)--(C/C++)
java·c语言·开发语言·c++·qt·算法·leetcode
蓝倾9768 小时前
小红书获取用户作品列表API接口操作指南
java·服务器·前端·python·电商开放平台·开放api接口
q567315238 小时前
告别低效:构建健壮R爬虫的工程思维
开发语言·爬虫·r语言
Seven978 小时前
剑指offer-28、数组中出现次数超过⼀半的数字
java
浮游本尊8 小时前
Java学习第19天 - 分布式缓存与Redis高级应用
java
bemyrunningdog8 小时前
DTO与POJO:核心差异与最佳实践
java