源本科技 | 码上会

Mapper 层选装件

2026/04/02
4
0

引言

MyBatis-Plus(简称 MP)的Mapper 选装件是官方提供的增强扩展方法,用于弥补基础 CRUD 方法的功能短板,解决常规业务中批量操作、强制更新、逻辑删除自动填充等高频痛点。所有选装件统一存放于: com.baomidou.mybatisplus.extension.injector.methods 包下,必须配合 SQL 注入器全局注册后才能使用,无法直接调用。


SQL 注入器配置

这是使用所有选装件的必备前提,未配置会导致方法无法识别,抛出绑定异常。

全局注入配置类

创建配置类,注册需要使用的选装件:

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.injector.methods.AlwaysUpdateSomeColumnById;
import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn;
import com.baomidou.mybatisplus.extension.injector.methods.LogicDeleteByIdWithFill;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.core.injector.SqlInjector;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.List;

@Configuration
public class MyBatisPlusConfig {

    /**
     * 自定义 SQL 注入器,注册选装件
     */
    @Bean
    public SqlInjector sqlInjector() {
        return new DefaultSqlInjector() {
            @Override
            public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
                // 1. 获取 MP 自带的基础方法
                List<AbstractMethod> methodList = super.getMethodList(mapperClass);
                // 2. 添加需要使用的选装件(按需添加,无需全部注册)
                methodList.add(new AlwaysUpdateSomeColumnById()); // 强制更新指定字段
                methodList.add(new InsertBatchSomeColumn());    // 批量插入指定字段
                methodList.add(new LogicDeleteByIdWithFill()); // 逻辑删除+自动填充
                return methodList;
            }
        };
    }

    // 分页插件(常规配置,非选装件必需)
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

接口显式声明方法

选装件不会自动注入,必须在自定义 Mapper 中手动声明方法

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;

public interface UserMapper extends BaseMapper<User> {

    // 1. 强制更新指定字段(选装件)
    int alwaysUpdateSomeColumnById(@Param("et") User entity);

    // 2. 批量插入指定字段(选装件)
    int insertBatchSomeColumn(List<User> entityList);

    // 3. 逻辑删除+自动填充(选装件)
    int logicDeleteByIdWithFill(@Param("et") User entity);
}

三大选装件

alwaysUpdateSomeColumnById

方法签名int alwaysUpdateSomeColumnById(T entity);

核心功能

根据 ID 强制更新指定字段,无论字段是否为 null/ 是否修改

  • 区别于 updateById()updateById() 会忽略 null 字段,仅更新非空字段

  • 区别于 update():该方法强制更新注解标记的字段,适合固定字段(更新时间、版本号)

配置要求

实体字段必须添加 @TableField(updateStrategy = FieldStrategy.ALWAYS) 注解:

import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import java.time.LocalDateTime;

@Data
public class User {
    private Long id;
    private String username;

    // 强制更新字段:每次调用都会更新,无论是否赋值
    @TableField(updateStrategy = FieldStrategy.ALWAYS)
    private LocalDateTime updateTime;

    // 版本号(强制更新场景)
    @TableField(updateStrategy = FieldStrategy.ALWAYS)
    private Integer version;
}

使用场景

  • 每次更新数据必须刷新更新时间

  • 乐观锁版本号强制自增

  • 无需手动赋值,MP 自动生成更新 SQL

调用示例

// 仅传入 ID,updateTime 会被强制更新
User user = new User();
user.setId(1L);
userMapper.alwaysUpdateSomeColumnById(user);

insertBatchSomeColumn

方法签名int insertBatchSomeColumn(List<T> entityList);

核心功能

高性能批量插入,仅插入非空 / 指定字段

  • 底层生成 单条 INSERT 语句INSERT INTO table VALUES (),(),()),性能远超循环插入

  • 只插入非 null 字段,跳过 null 字段,数据库自动使用默认值

核心优势

  • 性能提升:1000 条数据仅执行 1 次 SQL,比循环插入快 5~10 倍

  • 灵活可控:只插入需要的字段,避免冗余数据

使用场景

  • 大批量数据导入(Excel 导入、批量注册用户)

  • 仅插入部分字段,保留数据库默认值

调用示例

List<User> userList = new ArrayList<>();
for (int i = 0; i < 100; i++) {
    User user = new User();
    user.setUsername("test" + i);
    // 不设置 id(数据库自增)、不设置 createTime(自动填充)
    userList.add(user);
}
// 批量插入,仅插入 username 等非空字段
userMapper.insertBatchSomeColumn(userList);

logicDeleteByIdWithFill

方法签名int logicDeleteByIdWithFill(T entity);

核心功能

逻辑删除 + 自动填充删除字段

  • 逻辑删除:不物理删除数据,通过 deleted 字段标记为已删除

  • 自动填充:删除时自动填充 deleteTimedeleteUser 等字段

配置要求

实体类配置逻辑删除注解 + 自动填充

import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import java.time.LocalDateTime;

@Data
public class User {
    private Long id;

    // 逻辑删除字段:0-未删除,1-已删除
    @TableLogic
    @TableField(fill = FieldFill.INSERT)
    private Integer deleted;

    // 删除时间(自动填充)
    @TableField(fill = FieldFill.UPDATE)
    private LocalDateTime deleteTime;

    // 删除人(自动填充)
    @TableField(fill = FieldFill.UPDATE)
    private String deleteUser;
}

配置自动填充处理器

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    // 插入时填充
    @Override
    public void insertFill(MetaObject metaObject) {
        this.strictInsertFill(metaObject, "deleted", Integer.class, 0);
    }

    // 逻辑删除时填充
    @Override
    public void updateFill(MetaObject metaObject) {
        this.strictUpdateFill(metaObject, "deleteTime", LocalDateTime.class, LocalDateTime.now());
        this.strictUpdateFill(metaObject, "deleteUser", String.class, "系统管理员");
    }
}

使用场景

  • 业务要求数据不可物理删除,仅标记删除

  • 删除时需要记录删除时间、操作人

调用示例

User user = new User();
user.setId(1L);
// 逻辑删除,自动填充 deleteTime、deleteUser
userMapper.logicDeleteByIdWithFill(user);