设计模式扩展 MyBatis Plus BaseMapper接口

发布于:2025-04-01 ⋅ 阅读:(18) ⋅ 点赞:(0)

pom

<dependency>
	<groupId>com.github.yulichang</groupId>
	<artifactId>mybatis-plus-join-boot-starter</artifactId> <!-- MyBatis 联表查询 -->
</dependency>

java


/**
 1. 在 MyBatis Plus 的 BaseMapper 的基础上拓展,提供更多的能力
 2.  3. 1. {@link BaseMapper} 为 MyBatis Plus 的基础接口,提供基础的 CRUD 能力
 4. 2. {@link MPJBaseMapper} 为 MyBatis Plus Join 的基础接口,提供连表 Join 能力
 */
public interface BaseMapperX<T> extends MPJBaseMapper<T> {

    default PageResult<T> selectPage(SortablePageParam pageParam, @Param("ew") Wrapper<T> queryWrapper) {
        return selectPage(pageParam, pageParam.getSortingFields(), queryWrapper);
    }

    default PageResult<T> selectPage(PageParam pageParam, @Param("ew") Wrapper<T> queryWrapper) {
        return selectPage(pageParam, null, queryWrapper);
    }

    default PageResult<T> selectPage(PageParam pageParam, Collection<SortingField> sortingFields, @Param("ew") Wrapper<T> queryWrapper) {
        // 特殊:不分页,直接查询全部
        if (PageParam.PAGE_SIZE_NONE.equals(pageParam.getPageSize())) {
            List<T> list = selectList(queryWrapper);
            return new PageResult<>(list, (long) list.size());
        }

        // MyBatis Plus 查询
        IPage<T> mpPage = MyBatisUtils.buildPage(pageParam, sortingFields);
        selectPage(mpPage, queryWrapper);
        // 转换返回
        return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
    }

    default <D> PageResult<D> selectJoinPage(PageParam pageParam, Class<D> clazz, MPJLambdaWrapper<T> lambdaWrapper) {
        // 特殊:不分页,直接查询全部
        if (PageParam.PAGE_SIZE_NONE.equals(pageParam.getPageSize())) {
            List<D> list = selectJoinList(clazz, lambdaWrapper);
            return new PageResult<>(list, (long) list.size());
        }

        // MyBatis Plus Join 查询
        IPage<D> mpPage = MyBatisUtils.buildPage(pageParam);
        mpPage = selectJoinPage(mpPage, clazz, lambdaWrapper);
        // 转换返回
        return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
    }

    default <DTO> PageResult<DTO> selectJoinPage(PageParam pageParam, Class<DTO> resultTypeClass, MPJBaseJoin<T> joinQueryWrapper) {
        IPage<DTO> mpPage = MyBatisUtils.buildPage(pageParam);
        selectJoinPage(mpPage, resultTypeClass, joinQueryWrapper);
        // 转换返回
        return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
    }

    default T selectOne(String field, Object value) {
        return selectOne(new QueryWrapper<T>().eq(field, value));
    }



    default T selectOne(SFunction<T, ?> field, Object value) {
        return selectOne(new LambdaQueryWrapper<T>().eq(field, value));
    }





    default T selectOne(String field1, Object value1, String field2, Object value2) {
        return selectOne(new QueryWrapper<T>().eq(field1, value1).eq(field2, value2));
    }

    default T selectOne(SFunction<T, ?> field1, Object value1, SFunction<T, ?> field2, Object value2) {
        return selectOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2));
    }

    default T selectOne(SFunction<T, ?> field1, Object value1, SFunction<T, ?> field2, Object value2,
                        SFunction<T, ?> field3, Object value3) {
        return selectOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2)
                .eq(field3, value3));
    }

    default Long selectCount() {
        return selectCount(new QueryWrapper<>());
    }

    default Long selectCount(String field, Object value) {
        return selectCount(new QueryWrapper<T>().eq(field, value));
    }

    default Long selectCount(SFunction<T, ?> field, Object value) {
        return selectCount(new LambdaQueryWrapper<T>().eq(field, value));
    }

    default List<T> selectList() {
        return selectList(new QueryWrapper<>());
    }

    default List<T> selectList(String field, Object value) {
        return selectList(new QueryWrapper<T>().eq(field, value));
    }

    default List<T> selectList(SFunction<T, ?> field, Object value) {
        return selectList(new LambdaQueryWrapper<T>().eq(field, value));
    }

    default List<T> selectList(String field, Collection<?> values) {
        if (CollUtil.isEmpty(values)) {
            return CollUtil.newArrayList();
        }
        return selectList(new QueryWrapper<T>().in(field, values));
    }

    default List<T> selectList(SFunction<T, ?> field, Collection<?> values) {
        if (CollUtil.isEmpty(values)) {
            return CollUtil.newArrayList();
        }
        return selectList(new LambdaQueryWrapper<T>().in(field, values));
    }

    default List<T> selectList(SFunction<T, ?> field1, Object value1, SFunction<T, ?> field2, Object value2) {
        return selectList(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2));
    }

    /**
     * 批量插入,适合大量数据插入
     *
     * @param entities 实体们
     */
    default Boolean insertBatch(Collection<T> entities) {
        // 特殊:SQL Server 批量插入后,获取 id 会报错,因此通过循环处理
        DbType dbType = JdbcUtils.getDbType();
        if (JdbcUtils.isSQLServer(dbType)) {
            entities.forEach(this::insert);
            return CollUtil.isNotEmpty(entities);
        }
        return Db.saveBatch(entities);
    }

    /**
     * 批量插入,适合大量数据插入
     *
     * @param entities 实体们
     * @param size     插入数量 Db.saveBatch 默认为 1000
     */
    default Boolean insertBatch(Collection<T> entities, int size) {
        // 特殊:SQL Server 批量插入后,获取 id 会报错,因此通过循环处理
        DbType dbType = JdbcUtils.getDbType();
        if (JdbcUtils.isSQLServer(dbType)) {
            entities.forEach(this::insert);
            return CollUtil.isNotEmpty(entities);
        }
        return Db.saveBatch(entities, size);
    }

    default int updateBatch(T update) {
        return update(update, new QueryWrapper<>());
    }

    default Boolean updateBatch(Collection<T> entities) {
        return Db.updateBatchById(entities);
    }

    default Boolean updateBatch(Collection<T> entities, int size) {
        return Db.updateBatchById(entities, size);
    }

    default int delete(String field, String value) {
        return delete(new QueryWrapper<T>().eq(field, value));
    }

    default int delete(SFunction<T, ?> field, Object value) {
        return delete(new LambdaQueryWrapper<T>().eq(field, value));
    }
}

一、核心定位

BaseMapperX 是 MyBatis Plus BaseMapper 的增强扩展接口,通过 统一封装高频操作 和 联表查询支持,解决以下痛点:

  1. 减少样板代码:内置分页、单字段查询等高频方法
  2. 类型安全:通过 Lambda 表达式避免字段名硬编码
  3. 多表联查简化:集成 MyBatis Plus Join 能力
  4. 数据库兼容:处理 SQL Server 等特殊批量插入场景

二、关键增强功能

1. 分页查询统一封装

// 原生 MyBatis Plus 分页
IPage<UserDO> page = new Page<>(1, 10);
mapper.selectPage(page, queryWrapper);
PageResult<UserDO> result = new PageResult<>(page.getRecords(), page.getTotal());

// 使用 BaseMapperX 简化后
PageResult<UserDO> result = mapper.selectPage(pageParam, queryWrapper);

2. 联表分页查询

PageResult<UserDeptVO> result = mapper.selectJoinPage(
    pageParam, UserDeptVO.class, 
    new MPJLambdaWrapperX<UserDO>()
        .selectAll(UserDO.class)
        .leftJoin(DepartmentDO.class, ...)
);

3. 高频单表操作

// 根据单个字段查询
UserDO user = mapper.selectOne(UserDO::getUsername, "yudaoyuanma");

// 根据多个字段查询
UserDO user = mapper.selectOne(
    UserDO::getUsername, "yudaoyuanma",
    UserDO::getStatus, 0
);

// 批量插入(自动处理 SQL Server 兼容)
mapper.insertBatch(users);

三、设计模式解析

1. 模板方法模式(Template Method)

  • 体现:selectPage 方法统一分页处理流程
public default PageResult<T> selectPage(PageParam pageParam, Wrapper<T> queryWrapper) {
    // 1. 构建分页参数(模板步骤)
    IPage<T> mpPage = MyBatisUtils.buildPage(pageParam);
    // 2. 执行查询(具体实现由 MyBatis Plus 提供)
    selectPage(mpPage, queryWrapper);
    // 3. 结果转换(模板步骤)
    return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
}

2. 门面模式(Facade)

  • 体现:对复杂联表查询进行高层抽象
public default <D> PageResult<D> selectJoinPage(...) {
    // 隐藏联表查询的复杂性
    IPage<D> mpPage = MyBatisUtils.buildPage(pageParam);
    selectJoinPage(mpPage, clazz, lambdaWrapper);
    return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
}

3. 策略模式(Strategy)

  • 体现:根据数据库类型切换批量插入策略
default Boolean insertBatch(Collection<T> entities) {
    if (JdbcUtils.isSQLServer()) { // SQL Server 策略
        entities.forEach(this::insert);
    } else { // 通用策略
        Db.saveBatch(entities);
    }
    return true;
}

四、与原生 API 对比

功能 MyBatis Plus BaseMapper BaseMapperX
分页封装 需手动处理 IPage 对象 直接返回 PageResult 统一结构
联表查询 不支持 支持连表分页查询与 VO 映射
字段条件方法 需手动写 QueryWrapper 提供 selectOne(field, value) 等快捷方法
批量插入兼容性 需自行处理数据库差异 内置 SQL Server 特殊逻辑

网站公告

今日签到

点亮在社区的每一天
去签到