package cn.iocoder.yudao.framework.mybatis.core.mapper; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.SortablePageParam; import cn.iocoder.yudao.framework.common.pojo.SortingField; import cn.iocoder.yudao.framework.mybatis.core.util.JdbcUtils; import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils; import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.support.SFunction; import com.baomidou.mybatisplus.extension.toolkit.Db; import com.github.yulichang.base.MPJBaseMapper; import com.github.yulichang.interfaces.MPJBaseJoin; import com.github.yulichang.wrapper.MPJLambdaWrapper; import org.apache.ibatis.annotations.Param; import java.util.Collection; import java.util.List; /** * 在 MyBatis Plus 的 BaseMapper 的基础上拓展,提供更多的能力 * * 1. {@link BaseMapper} 为 MyBatis Plus 的基础接口,提供基础的 CRUD 能力 * 2. {@link MPJBaseMapper} 为 MyBatis Plus Join 的基础接口,提供连表 Join 能力 */ public interface BaseMapperX extends MPJBaseMapper { default PageResult selectPage(SortablePageParam pageParam, @Param("ew") Wrapper queryWrapper) { return selectPage(pageParam, pageParam.getSortingFields(), queryWrapper); } default PageResult selectPage(PageParam pageParam, @Param("ew") Wrapper queryWrapper) { return selectPage(pageParam, null, queryWrapper); } default PageResult selectPage(PageParam pageParam, Collection sortingFields, @Param("ew") Wrapper queryWrapper) { // 特殊:不分页,直接查询全部 if (PageParam.PAGE_SIZE_NONE.equals(pageParam.getPageSize())) { MyBatisUtils.addOrder(queryWrapper, sortingFields); List list = selectList(queryWrapper); return new PageResult<>(list, (long) list.size()); } // MyBatis Plus 查询 IPage mpPage = MyBatisUtils.buildPage(pageParam, sortingFields); selectPage(mpPage, queryWrapper); // 转换返回 return new PageResult<>(mpPage.getRecords(), mpPage.getTotal()); } default PageResult selectJoinPage(PageParam pageParam, Class clazz, MPJLambdaWrapper lambdaWrapper) { // 特殊:不分页,直接查询全部 if (PageParam.PAGE_SIZE_NONE.equals(pageParam.getPageSize())) { List list = selectJoinList(clazz, lambdaWrapper); return new PageResult<>(list, (long) list.size()); } // MyBatis Plus Join 查询 IPage mpPage = MyBatisUtils.buildPage(pageParam); mpPage = selectJoinPage(mpPage, clazz, lambdaWrapper); // 转换返回 return new PageResult<>(mpPage.getRecords(), mpPage.getTotal()); } /** * 执行分页查询并返回结果。 * * @param pageParam 分页参数,包含页码、每页条数和排序字段信息。如果 pageSize 为 {@link PageParam#PAGE_SIZE_NONE},则不分页,直接查询所有数据。 * @param clazz 结果集的类类型 * @param lambdaWrapper MyBatis Plus Join 查询条件包装器 * @param 结果集的泛型类型 * @return 返回分页查询的结果,包括总记录数和当前页的数据列表 */ default PageResult selectJoinPage(SortablePageParam pageParam, Class clazz, MPJLambdaWrapper lambdaWrapper) { // 特殊:不分页,直接查询全部 if (PageParam.PAGE_SIZE_NONE.equals(pageParam.getPageSize())) { List list = selectJoinList(clazz, lambdaWrapper); return new PageResult<>(list, (long) list.size()); } // MyBatis Plus Join 查询 IPage mpPage = MyBatisUtils.buildPage(pageParam, pageParam.getSortingFields()); mpPage = selectJoinPage(mpPage, clazz, lambdaWrapper); // 转换返回 return new PageResult<>(mpPage.getRecords(), mpPage.getTotal()); } default PageResult selectJoinPage(PageParam pageParam, Class resultTypeClass, MPJBaseJoin joinQueryWrapper) { IPage 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().eq(field, value)); } default T selectOne(SFunction field, Object value) { return selectOne(new LambdaQueryWrapper().eq(field, value)); } default T selectOne(String field1, Object value1, String field2, Object value2) { return selectOne(new QueryWrapper().eq(field1, value1).eq(field2, value2)); } default T selectOne(SFunction field1, Object value1, SFunction field2, Object value2) { return selectOne(new LambdaQueryWrapper().eq(field1, value1).eq(field2, value2)); } default T selectOne(SFunction field1, Object value1, SFunction field2, Object value2, SFunction field3, Object value3) { return selectOne(new LambdaQueryWrapper().eq(field1, value1).eq(field2, value2).eq(field3, value3)); } /** * 获得满足条件的一条记录,并使用 FOR UPDATE 锁定。 * * 注意:需要在事务中调用,否则锁会立即释放。 * * @param queryWrapper 查询条件 * @return 实体 */ default T selectOneForUpdate(LambdaQueryWrapper queryWrapper) { return selectOne(queryWrapper.last("FOR UPDATE")); } default T selectOneForUpdate(SFunction field, Object value) { return selectOneForUpdate(new LambdaQueryWrapper().eq(field, value)); } default T selectOneForUpdate(SFunction field1, Object value1, SFunction field2, Object value2) { return selectOneForUpdate(new LambdaQueryWrapper().eq(field1, value1).eq(field2, value2)); } default T selectOneForUpdate(SFunction field1, Object value1, SFunction field2, Object value2, SFunction field3, Object value3) { return selectOneForUpdate(new LambdaQueryWrapper().eq(field1, value1).eq(field2, value2).eq(field3, value3)); } /** * 获取满足条件的第 1 条记录 * * 目的:解决并发场景下,插入多条记录后,使用 selectOne 会报错的问题 * * @param field 字段名 * @param value 字段值 * @return 实体 */ default T selectFirstOne(SFunction field, Object value) { // 如果明确使用 MySQL 等场景,可以考虑使用 LIMIT 1 进行优化 List list = selectList(new LambdaQueryWrapper().eq(field, value)); return CollUtil.getFirst(list); } default T selectFirstOne(SFunction field1, Object value1, SFunction field2, Object value2) { List list = selectList(new LambdaQueryWrapper().eq(field1, value1).eq(field2, value2)); return CollUtil.getFirst(list); } default T selectFirstOne(SFunction field1, Object value1, SFunction field2, Object value2, SFunction field3, Object value3) { List list = selectList(new LambdaQueryWrapper().eq(field1, value1).eq(field2, value2).eq(field3, value3)); return CollUtil.getFirst(list); } default Long selectCount() { return selectCount(new QueryWrapper<>()); } default Long selectCount(String field, Object value) { return selectCount(new QueryWrapper().eq(field, value)); } default Long selectCount(SFunction field, Object value) { return selectCount(new LambdaQueryWrapper().eq(field, value)); } default List selectList() { return selectList(new QueryWrapper<>()); } default List selectList(String field, Object value) { return selectList(new QueryWrapper().eq(field, value)); } default List selectList(SFunction field, Object value) { return selectList(new LambdaQueryWrapper().eq(field, value)); } default List selectList(String field, Collection values) { if (CollUtil.isEmpty(values)) { return CollUtil.newArrayList(); } return selectList(new QueryWrapper().in(field, values)); } default List selectList(SFunction field, Collection values) { if (CollUtil.isEmpty(values)) { return CollUtil.newArrayList(); } return selectList(new LambdaQueryWrapper().in(field, values)); } default List selectList(SFunction field1, Object value1, SFunction field2, Object value2) { return selectList(new LambdaQueryWrapper().eq(field1, value1).eq(field2, value2)); } /** * 批量插入,适合大量数据插入 * * @param entities 实体们 */ default Boolean insertBatch(Collection 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 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 entities) { return Db.updateBatchById(entities); } default Boolean updateBatch(Collection entities, int size) { return Db.updateBatchById(entities, size); } default int delete(String field, String value) { return delete(new QueryWrapper().eq(field, value)); } default int delete(SFunction field, Object value) { return delete(new LambdaQueryWrapper().eq(field, value)); } default int deleteBatch(SFunction field, Collection values) { if (CollUtil.isEmpty(values)) { return 0; } return delete(new LambdaQueryWrapper().in(field, values)); } }