MyBatis-Plus

MyBatis-Plus(简称MP)是MyBatis社区的一个增强工具包,它在MyBatis的基础上进行了扩展,封装了很多有用的功能,提高了开发效率。MyBatis-Plus中包含了许多常用的增删改查的方法,还有分页查询、条件构造器、乐观锁、多租户、性能分析等功能。

以下是MyBatis-Plus的一些特点:

  1. 简化开发:MyBatis-Plus可以通过代码自动生成器快速生成CRUD方法的代码,极大地提高了开发效率。
  2. 增删改查方法:MyBatis-Plus封装了通用的增删改查方法,无需手写SQL语句。
  3. 集成分页插件:MyBatis-Plus集成了分页插件,使用简单,可以轻松实现分页操作。
  4. 条件构造器:MyBatis-Plus提供了条件构造器,可以通过代码的形式构造复杂的SQL查询语句。
  5. 乐观锁:MyBatis-Plus提供了乐观锁的功能,避免了并发操作时的数据冲突。
  6. 多租户:MyBatis-Plus支持多租户,可以通过配置实现多租户系统的开发。
  7. 性能分析:MyBatis-Plus集成了性能分析插件,可以分析SQL查询的性能瓶颈,帮助优化SQL语句,提高查询效率。

总之,MyBatis-Plus是一个非常优秀的MyBatis增强工具包,其功能强大且易于使用,在实际开发中也能够显著地提高开发效率和工作效率。

Java Optional

Java OptionalJava 8中引入的一个类,用于表示一个值可能存在也可能不存在。它的主要目的是减少空指针异常。

Java Optional类有两个重要的方法:isPresent()get()isPresent()方法用于检查值是否存在,get()方法用于获取值。如果值不存在,get()方法会抛出NoSuchElementException异常。

Java Optional还有很多有用的方法,比如orElse()orElseGet()方法。这些方法可以帮助我们处理值不存在的情况。

Java Optional是一个泛型类,因此可以用于处理任何类型的值。使用Java Optional的主要优点是可以避免空指针异常,提高代码健壮性。

堵点

MyBatis-Plus提供了很好的CURD体验,大大加强了开发的效率,其Lambda表达式式的方式也大大增强了用户的体验,但是MyBatis-Plus返回的参数仍然会在实际项目中被忽略空指针问题,笔者的朋友和同事就经常因为空指针问题(主要是忘记)经常被测试吐槽,故此通过可以使用Optional来增强Mybatis-plus的体验,一定程度上可以避免“忘记”判空带来的空指针问题。

代码

项目中引入MyBatis-Plus,新建OptionalBaseMapper文件,实现BaseMapper,具体代码如下:

@SuppressWarnings({"DuplicatedCode", "unused"})
public interface OptionalBaseMapper<T> extends BaseMapper<T> {

    // ======================================= 批量插入 ========================================

    /**
     * 批量插入 仅适用于mysql
     *
     * @param entityList 实体列表
     * @return 影响行数
     */
    Integer insertBatchSomeColumn(Collection<T> entityList);

    /**
     * 逐条插入,适合少量数据插入,或者对性能要求不高的场景
     * <p>
     * 如果大量,请使用 {@link com.baomidou.mybatisplus.extension.service.impl.ServiceImpl#saveBatch(Collection)} 方法
     * 使用示例,可见 RoleMenuBatchInsertMapper、UserRoleBatchInsertMapper 类
     *
     * @param entities 实体们
     */
    default void insertBatch(Collection<T> entities) {
        entities.forEach(this::insert);
    }

    // ======================================= 查询数量 ========================================


    /**
     * 根据 Wrapper 条件,查询总记录数
     *
     * @param queryWrapper 实体对象封装操作类(可以为 null)
     */
    default Optional<Long> getCount(Wrapper<T> queryWrapper) {
        Long count = selectCount(queryWrapper);
        return ObjectUtil.isNull(count) ? Optional.empty() : Optional.of(count);
    }

    /**
     * 查询指定字段值数量
     *
     * @param field field
     * @param value value
     */
    default Optional<Long> selectCount(String field, Object value) {
        Long count = selectCount(new QueryWrapper<T>().eq(field, value));
        return ObjectUtil.isNull(count) ? Optional.empty() : Optional.of(count);
    }

    /**
     * 查询指定字段值数量
     *
     * @param field field
     * @param value value
     */
    default Optional<Long> selectCount(SFunction<T, ?> field, Object value) {
        Long count = selectCount(new LambdaQueryWrapper<T>().eq(field, value));
        return ObjectUtil.isNull(count) ? Optional.empty() : Optional.of(count);
    }

    // ======================================= 查询一个 ========================================


    /**
     * 根据 ID 查询
     *
     * @param id 主键ID
     */
    default Optional<T> getById(Serializable id) {
        T t = selectById(id);
        return ObjectUtil.isNull(t) ? Optional.empty() : Optional.of(t);
    }


    /**
     * 根据 entity 条件,查询一条记录
     * <p>查询一条记录,例如 qw.last("limit 1") 限制取一条记录, 注意:多条数据会报异常</p>
     *
     * @param queryWrapper 实体对象封装操作类(可以为 null)
     */
    default Optional<T> getOne(Wrapper<T> queryWrapper) {
        T t = selectOne(queryWrapper);
        return ObjectUtil.isNull(t) ? Optional.empty() : Optional.of(t);
    }

    /**
     * 查询一个
     *
     * @param field field
     * @param value value
     */
    default Optional<T> getOne(String field, Object value) {
        return getOne(new QueryWrapper<T>().eq(field, value));
    }

    /**
     * 查询一个
     *
     * @param field field
     * @param value value
     */
    default Optional<T> getOne(SFunction<T, ?> field, Object value) {
        return getOne(new LambdaQueryWrapper<T>().eq(field, value));
    }

    /**
     * 查询一个
     *
     * @param field1 field1
     * @param value1 value1
     * @param field2 field2
     * @param value2 value2
     */
    default Optional<T> getTwo(String field1, Object value1, String field2, Object value2) {
        return getOne(new QueryWrapper<T>().eq(field1, value1).eq(field2, value2));
    }

    /**
     * 查询一个
     *
     * @param field1 field1
     * @param value1 value1
     * @param field2 field2
     * @param value2 value2
     */
    default Optional<T> getTwo(SFunction<T, ?> field1, Object value1, SFunction<T, ?> field2, Object value2) {
        return getOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2));
    }


    // ======================================= 查询多个 ========================================


    /**
     * 查询(根据ID 批量查询)
     *
     * @param idList 主键ID列表(不能为 null 以及 empty)
     */
    default Optional<List<T>> listBatchIds(Collection<? extends Serializable> idList) {
        List<T> list = selectBatchIds(idList);
        return CollUtil.isEmpty(list) ? Optional.empty() : Optional.of(list);
    }

    /**
     * 根据 entity 条件,查询全部记录
     *
     * @param queryWrapper 实体对象封装操作类(可以为 null)
     */
    default Optional<List<T>> list(Wrapper<T> queryWrapper) {
        List<T> list = selectList(queryWrapper);
        return CollUtil.isEmpty(list) ? Optional.empty() : Optional.of(list);
    }

    /**
     * 列表查询
     *
     * @param field field
     * @param value value
     */
    default Optional<List<T>> list(String field, Object value) {
        List<T> list = selectList(new QueryWrapper<T>().eq(field, value));
        return CollUtil.isEmpty(list) ? Optional.empty() : Optional.of(list);
    }

    /**
     * 列表查询
     *
     * @param field field
     * @param value value
     */
    default Optional<List<T>> list(SFunction<T, ?> field, Object value) {
        List<T> list = selectList(new LambdaQueryWrapper<T>().eq(field, value));
        return CollUtil.isEmpty(list) ? Optional.empty() : Optional.of(list);
    }

    /**
     * 列表查询
     *
     * @param field  field
     * @param values values
     */
    default Optional<List<T>> list(String field, Collection<?> values) {
        List<T> list = selectList(new QueryWrapper<T>().in(field, values));
        return CollUtil.isEmpty(list) ? Optional.empty() : Optional.of(list);
    }

    /**
     * 列表查询
     *
     * @param field  field
     * @param values values
     */
    default Optional<List<T>> list(SFunction<T, ?> field, Collection<?> values) {
        List<T> list = selectList(new LambdaQueryWrapper<T>().in(field, values));
        return CollUtil.isEmpty(list) ? Optional.empty() : Optional.of(list);
    }


    /**
     * 查询(根据 columnMap 条件)
     *
     * @param columnMap 表字段 map 对象
     */
    default Optional<List<T>> listByMaps(Map<String, Object> columnMap) {
        List<T> list = selectByMap(columnMap);
        return CollUtil.isEmpty(list) ? Optional.empty() : Optional.of(list);
    }

    /**
     * 根据 Wrapper 条件,查询全部记录
     *
     * @param queryWrapper 实体对象封装操作类(可以为 null)
     */
    default Optional<List<Map<String, Object>>> maps(Wrapper<T> queryWrapper) {
        List<Map<String, Object>> maps = selectMaps(queryWrapper);
        return CollUtil.isEmpty(maps) ? Optional.empty() : Optional.of(maps);
    }

    /**
     * 根据 Wrapper 条件,查询全部记录
     * <p>注意: 只返回第一个字段的值</p>
     *
     * @param queryWrapper 实体对象封装操作类(可以为 null)
     */
    default Optional<List<Object>> listObjs(Wrapper<T> queryWrapper) {
        List<Object> objects = selectObjs(queryWrapper);
        return CollUtil.isEmpty(objects) ? Optional.empty() : Optional.of(objects);
    }


    // ======================================= 分页 ========================================

    /**
     * 分页
     *
     * @param pageParam    分页参数 需继承PageParam
     * @param queryWrapper queryWrapper
     */
    default PageResult<T> selectPage(PageParam pageParam, @Param("ew") Wrapper<T> queryWrapper) {
        // MyBatis Plus 查询
        IPage<T> mpPage = MyBatisUtils.buildPage(pageParam);
        selectPage(mpPage, queryWrapper);
        // 转换返回
        return new PageResult<>(mpPage.getRecords(), mpPage.getTotal(), mpPage.getPages(), mpPage.getCurrent(), mpPage.getSize());
    }

    /**
     * 根据 entity 条件,查询全部记录(并翻页)
     *
     * @param sortingFields 排序字段
     * @param pageParam     分页查询条件
     * @param queryWrapper  实体对象封装操作类(可以为 null)
     */
    default PageResult<T> selectPage(PageParam pageParam, @Param("ew") Wrapper<T> queryWrapper, Collection<SortingField> sortingFields) {
        // MyBatis Plus 查询
        IPage<T> mpPage = MyBatisUtils.buildPage(pageParam, sortingFields);
        selectPage(mpPage, queryWrapper);
        // 转换返回
        return new PageResult<>(mpPage.getRecords(), mpPage.getTotal(), mpPage.getPages(), mpPage.getCurrent(), mpPage.getSize());
    }
}

最后,在dao层,继承从BaseMapper换成OptionalBaseMapper即可。

如果觉得我的文章对你有用,请随意赞赏