MyBatis-Plus
MyBatis-Plus
(简称MP)是MyBatis
社区的一个增强工具包,它在MyBatis
的基础上进行了扩展,封装了很多有用的功能,提高了开发效率。MyBatis-Plus
中包含了许多常用的增删改查的方法,还有分页查询、条件构造器、乐观锁、多租户、性能分析等功能。
以下是MyBatis-Plus
的一些特点:
- 简化开发:
MyBatis-Plus
可以通过代码自动生成器快速生成CRUD方法的代码,极大地提高了开发效率。 - 增删改查方法:
MyBatis-Plus
封装了通用的增删改查方法,无需手写SQL语句。 - 集成分页插件:
MyBatis-Plus
集成了分页插件,使用简单,可以轻松实现分页操作。 - 条件构造器:
MyBatis-Plus
提供了条件构造器,可以通过代码的形式构造复杂的SQL查询语句。 - 乐观锁:
MyBatis-Plus
提供了乐观锁的功能,避免了并发操作时的数据冲突。 - 多租户:
MyBatis-Plus
支持多租户,可以通过配置实现多租户系统的开发。 - 性能分析:
MyBatis-Plus
集成了性能分析插件,可以分析SQL查询的性能瓶颈,帮助优化SQL语句,提高查询效率。
总之,MyBatis-Plus
是一个非常优秀的MyBatis
增强工具包,其功能强大且易于使用,在实际开发中也能够显著地提高开发效率和工作效率。
Java Optional
Java Optional
是Java 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
即可。