深入理解 MyBatis-Plus 的 `BaseMapper`

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

1. BaseMapper 简介

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

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

定义位置

java

复制代码

package com.baomidou.mybatisplus.core.mapper;

public interface BaseMapper extends Mapper {

// 内置了丰富的 CRUD 方法

}

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

java

复制代码

@Mapper

public interface UserMapper extends BaseMapper {

}

2. 常用方法一览

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

(1)插入

java

复制代码

int insert(T entity);

功能:插入一条记录

特点:只插入非 null 字段,支持自增主键回填

(2)删除

java

复制代码

int deleteById(Serializable id);

int deleteByMap(@Param(Constants.COLUMN_MAP) Map columnMap);

int delete(@Param(Constants.WRAPPER) Wrapper wrapper);

int deleteBatchIds(@Param(Constants.COLL) Collection 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 updateWrapper);

updateById:根据主键更新,null 值字段会被更新为 null

update :条件更新,配合 UpdateWrapper 使用

(4)查询

java

复制代码

T selectById(Serializable id);

List selectBatchIds(@Param(Constants.COLL) Collection idList);

List selectByMap(@Param(Constants.COLUMN_MAP) Map columnMap);

T selectOne(@Param(Constants.WRAPPER) Wrapper queryWrapper);

Integer selectCount(@Param(Constants.WRAPPER) Wrapper queryWrapper);

List selectList(@Param(Constants.WRAPPER) Wrapper queryWrapper);

List> selectMaps(@Param(Constants.WRAPPER) Wrapper queryWrapper);

List selectObjs(@Param(Constants.WRAPPER) Wrapper queryWrapper);

IPage selectPage(IPage page, @Param(Constants.WRAPPER) Wrapper queryWrapper);

IPage> selectMapsPage(IPage page, @Param(Constants.WRAPPER) Wrapper queryWrapper);

单条查询 :selectById, selectOne

批量查询 :selectBatchIds, selectList

分页查询 :selectPage, selectMapsPage

统计 :selectCount

Map 查询 :返回 Map,适合动态表格场景

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 {

}

插入

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().eq("age", 20));

更新

java

复制代码

User user = userMapper.selectById(1L);

user.setAge(25);

userMapper.updateById(user);

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

查询

java

复制代码

User user = userMapper.selectById(1L);

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

Page page = new Page<>(1, 10);

IPage userPage = userMapper.selectPage(page, new QueryWrapper().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. 使用注意事项

批量操作性能

insert 是逐条执行,不是批量插入

建议使用 saveBatch(来自 IService)或自定义 SQL 提升性能

空值更新

updateById 会将 null 字段更新为 null

如果想忽略 null 值,可以使用 UpdateWrapper.set()

多表查询

BaseMapper 仅支持单表操作

多表需要写自定义 SQL 或使用 @Select 注解

Wrapper 灵活性

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

例如:

java

复制代码

new LambdaQueryWrapper().eq(User::getName, "张三");

6. 总结

BaseMapper 是 MyBatis-Plus 提供的核心接口

内置丰富的 CRUD 方法,省去了大量模板代码

搭配 Wrapper 可实现灵活查询

局限性:仅支持单表,复杂场景需自定义 SQL