☰
MyBatis-Plus BaseMapper核心解析与实战应用
2026/10/14 14:26:36 网站建设 项目流程

1. 理解MyBatis-Plus中的BaseMapper

1.1 什么是BaseMapper

BaseMapper是MyBatis-Plus框架提供的一个核心接口,它封装了最基础的CRUD(Create, Read, Update, Delete)操作方法。当我们在DAO层接口中声明extends BaseMapper<UserEntity>时,实际上是在继承这个预置的通用接口。

这个设计采用了泛型编程的思想,<UserEntity>表示这个Mapper专门操作UserEntity类型的数据。MyBatis-Plus会在运行时自动为这个接口生成实现类,无需开发者手动编写SQL语句。

1.2 BaseMapper的核心方法

BaseMapper接口中预定义了约20个常用方法,主要包括:

// 插入操作 int insert(T entity); // 删除操作 int deleteById(Serializable id); int deleteByMap(@Param("cm") Map<String, Object> columnMap); int delete(@Param("ew") Wrapper<T> wrapper); // 更新操作 int updateById(@Param("et") T entity); int update(@Param("et") T entity, @Param("ew") Wrapper<T> updateWrapper); // 查询操作 T selectById(Serializable id); List<T> selectBatchIds(@Param("coll") Collection<? extends Serializable> idList); List<T> selectByMap(@Param("cm") Map<String, Object> columnMap); T selectOne(@Param("ew") Wrapper<T> queryWrapper); // 计数操作 Long selectCount(@Param("ew") Wrapper<T> queryWrapper);

这些方法已经覆盖了90%以上的单表操作场景,开发者无需再编写重复的SQL语句。

2. 泛型参数的作用与实现原理

2.1 泛型参数的意义

<UserEntity>这个泛型参数起到了三个关键作用:

  1. 类型安全:所有方法的参数和返回值都会自动适配UserEntity类型
  2. 表映射:框架会自动将UserEntity类与数据库表进行关联
  3. SQL生成:根据实体类属性自动生成对应的SQL语句

2.2 MyBatis-Plus的实现机制

当Spring容器启动时,MyBatis-Plus会通过以下步骤处理这个接口:

  1. 扫描所有继承BaseMapper的接口
  2. 使用动态代理技术生成实现类
  3. 解析泛型参数获取实体类类型
  4. 根据实体类注解(@TableName等)确定对应的数据库表
  5. 为每个方法生成对应的SQL实现

整个过程对开发者完全透明,这也是MyBatis-Plus"约定优于配置"理念的体现。

3. 实际开发中的应用场景

3.1 基础CRUD操作

继承BaseMapper后,我们可以直接使用预定义的方法:

// 插入用户 UserEntity user = new UserEntity(); user.setName("张三"); user.setAge(25); userMapper.insert(user); // 查询用户 UserEntity result = userMapper.selectById(1L); // 更新用户 user.setAge(26); userMapper.updateById(user); // 删除用户 userMapper.deleteById(1L);

3.2 配合Wrapper使用

BaseMapper的强大之处在于可以与Wrapper条件构造器配合使用:

// 条件查询 QueryWrapper<UserEntity> wrapper = new QueryWrapper<>(); wrapper.like("name", "张") .between("age", 20, 30) .orderByDesc("create_time"); List<UserEntity> users = userMapper.selectList(wrapper); // 条件更新 UpdateWrapper<UserEntity> updateWrapper = new UpdateWrapper<>(); updateWrapper.set("age", 30) .eq("name", "张三"); userMapper.update(null, updateWrapper);

4. 扩展与自定义

4.1 自定义SQL方法

虽然BaseMapper提供了丰富的方法,但有时我们仍需要自定义SQL:

public interface UserMapper extends BaseMapper<UserEntity> { @Select("SELECT * FROM user WHERE age > #{age}") List<UserEntity> selectByAgeGreaterThan(@Param("age") Integer age); }

MyBatis-Plus会智能地合并继承的方法和自定义方法。

4.2 多表联查解决方案

对于复杂的多表查询,建议采用以下方案:

  1. 使用@Select注解编写自定义SQL
  2. 创建VO类接收结果
  3. 在XML中定义resultMap处理复杂映射
@Select("SELECT u.*, d.dept_name FROM user u LEFT JOIN department d ON u.dept_id = d.id") List<UserVO> selectUserWithDept();

5. 性能优化与最佳实践

5.1 批量操作优化

BaseMapper提供了批量操作方法,但需要注意:

// 批量插入(实际是循环单条插入,性能一般) List<UserEntity> userList = ...; userMapper.insertBatchSomeColumn(userList); // 需要配置logic-not-delete-field // 真正高效的批量插入应该使用SQLSession SqlSession sqlSession = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH); UserMapper batchMapper = sqlSession.getMapper(UserMapper.class); for(UserEntity user : userList) { batchMapper.insert(user); } sqlSession.commit();

5.2 字段注解的正确使用

合理使用注解可以优化SQL生成:

@TableName("sys_user") // 指定表名 public class UserEntity { @TableId(type = IdType.AUTO) // 主键策略 private Long id; @TableField("user_name") // 字段映射 private String name; @TableField(exist = false) // 非表字段 private String tempValue; }

6. 常见问题排查

6.1 映射失败问题

当出现"Table 'xxx' doesn't exist"错误时,检查:

  1. 实体类是否有@TableName注解
  2. 数据库表名是否正确
  3. 是否配置了全局表名前缀(global-config.db-config.table-prefix)

6.2 主键冲突问题

主键策略配置不当会导致插入失败:

// 正确的主键策略配置 @TableId(type = IdType.AUTO) // 数据库自增 @TableId(type = IdType.ASSIGN_ID) // 雪花算法(默认) @TableId(type = IdType.INPUT) // 手动输入

6.3 逻辑删除配置

实现逻辑删除需要正确配置:

mybatis-plus: global-config: db-config: logic-delete-field: deleted # 逻辑删除字段名 logic-not-delete-value: 0 # 未删除值 logic-delete-value: 1 # 删除值

7. 源码解析与实现原理

7.1 动态代理机制

MyBatis-Plus通过MapperProxy实现接口方法的动态代理:

  1. 为每个Mapper接口创建代理对象
  2. 方法调用时,根据方法名和参数选择执行策略
  3. 对于BaseMapper方法,使用预定义的SQL模板
  4. 对于自定义方法,走原生MyBatis流程

7.2 SQL自动生成

核心类SqlMethod定义了各种操作对应的SQL模板:

public enum SqlMethod { INSERT("insert", "插入一条数据", "INSERT INTO %s %s VALUES %s"), DELETE_BY_ID("deleteById", "根据ID删除一条数据", "DELETE FROM %s WHERE %s=#{%s}"), SELECT_BY_ID("selectById", "根据ID查询一条数据", "SELECT %s FROM %s WHERE %s=#{%s}"), // 其他方法... }

框架会根据实体类信息填充这些模板中的占位符。

8. 高级特性与扩展点

8.1 自定义注入方法

通过ISqlInjector接口可以扩展BaseMapper:

public class MySqlInjector extends DefaultSqlInjector { @Override public List<AbstractMethod> getMethodList(Class<?> mapperClass) { List<AbstractMethod> methodList = super.getMethodList(mapperClass); methodList.add(new DeleteAll()); // 添加自定义方法 return methodList; } }

8.2 租户处理器

实现多租户数据隔离:

public class MyTenantHandler implements TenantLineHandler { @Override public Expression getTenantId() { return new StringValue(TenantContext.getCurrentTenant()); } @Override public String getTenantIdColumn() { return "tenant_id"; } @Override public boolean ignoreTable(String tableName) { return !"user".equals(tableName); // 指定哪些表需要过滤 } }

9. 版本差异与升级指南

9.1 3.x与2.x的主要区别

  1. 移除了AR(ActiveRecord)模式
  2. 条件构造器API重构
  3. 分页插件实现方式变化
  4. 主键策略调整

9.2 升级注意事项

  1. 检查所有Wrapper的使用方式
  2. 重新评估分页实现
  3. 测试批量操作方法
  4. 验证自动填充功能

10. 实战经验分享

在实际项目中,我们总结了以下经验:

  1. 复杂查询处理:对于超过3表关联的查询,建议使用原生MyBatis实现

  2. 性能监控:添加@InterceptorIgnore注解排除不需要监控的方法

@InterceptorIgnore(illegalSql = "true", blockAttack = "true") List<UserEntity> selectAll();
  1. 动态表名:实现IDynamicTableName接口处理分表场景
public class UserEntity implements IDynamicTableName { private String year; // 分表后缀 @Override public String getDynamicTableName() { return "user_" + year; } }
  1. 字段加密:通过@FieldEncrypt注解实现自动加解密
@FieldEncrypt private String password;
  1. 多数据源:结合@DS注解实现动态数据源切换
@DS("slave") // 指定从库 UserEntity selectById(Long id);

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询