From fc94326fddf76ae389cea7770f68fc00f17bfc80 Mon Sep 17 00:00:00 2001 From: geshanzsq <497301391@qq.com> Date: Sun, 9 Jun 2024 21:03:18 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E5=9F=BA=E7=A1=80=E6=A1=86=E6=9E=B6):=20?= =?UTF-8?q?=E5=B0=81=E8=A3=85=20MyBatis=20Plus=EF=BC=9B=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=20PageHelper=20=E5=88=86=E9=A1=B5=E6=8F=92=E4=BB=B6=EF=BC=9B?= =?UTF-8?q?=E6=89=A9=E5=B1=95=20SuperService=E3=80=81SuperMapper?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mogu_base/pom.xml | 7 + .../mougblog/base/mapper/SuperMapper.java | 84 +++++- .../base/mybatis/page/dto/PageDTO.java | 42 +++ .../base/mybatis/page/util/PageUtils.java | 54 ++++ .../mougblog/base/mybatis/page/vo/PageVO.java | 38 +++ .../base/mybatis/plugin/annotation/Query.java | 39 +++ .../plugin/constant/FieldConstant.java | 21 ++ .../base/mybatis/plugin/enums/QueryWay.java | 71 +++++ .../plugin/query/LambdaQueryWrapperPlus.java | 115 ++++++++ .../plugin/query/QueryWrapperPlus.java | 269 ++++++++++++++++++ .../base/mybatis/property/PageProperty.java | 36 +++ .../mybatis/reflect/GenericTypeUtils.java | 24 ++ .../mybatis/reflect/IGenericTypeResolver.java | 13 + .../reflect/SpringReflectionHelper.java | 20 ++ .../base/mybatis/util/MybatisUtils.java | 48 ++++ .../mougblog/base/service/SuperService.java | 74 ++++- .../base/serviceImpl/SuperServiceImpl.java | 17 ++ pom.xml | 1 + 18 files changed, 970 insertions(+), 3 deletions(-) create mode 100644 mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/page/dto/PageDTO.java create mode 100644 mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/page/util/PageUtils.java create mode 100644 mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/page/vo/PageVO.java create mode 100644 mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/plugin/annotation/Query.java create mode 100644 mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/plugin/constant/FieldConstant.java create mode 100644 mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/plugin/enums/QueryWay.java create mode 100644 mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/plugin/query/LambdaQueryWrapperPlus.java create mode 100644 mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/plugin/query/QueryWrapperPlus.java create mode 100644 mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/property/PageProperty.java create mode 100644 mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/reflect/GenericTypeUtils.java create mode 100644 mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/reflect/IGenericTypeResolver.java create mode 100644 mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/reflect/SpringReflectionHelper.java create mode 100644 mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/util/MybatisUtils.java diff --git a/mogu_base/pom.xml b/mogu_base/pom.xml index 9ccdbf505..38fa608e7 100644 --- a/mogu_base/pom.xml +++ b/mogu_base/pom.xml @@ -29,6 +29,13 @@ ${Hutool.version} + + + com.github.pagehelper + pagehelper-spring-boot-starter + ${pagehelper.version} + + diff --git a/mogu_base/src/main/java/com/moxi/mougblog/base/mapper/SuperMapper.java b/mogu_base/src/main/java/com/moxi/mougblog/base/mapper/SuperMapper.java index 05d5f4205..b0f5accb0 100644 --- a/mogu_base/src/main/java/com/moxi/mougblog/base/mapper/SuperMapper.java +++ b/mogu_base/src/main/java/com/moxi/mougblog/base/mapper/SuperMapper.java @@ -1,14 +1,94 @@ package com.moxi.mougblog.base.mapper; +import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.ClassUtils; +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; +import com.moxi.mougblog.base.mybatis.page.dto.PageDTO; +import com.moxi.mougblog.base.mybatis.page.vo.PageVO; +import com.moxi.mougblog.base.mybatis.plugin.query.QueryWrapperPlus; +import com.moxi.mougblog.base.mybatis.reflect.GenericTypeUtils; +import com.moxi.mougblog.base.mybatis.util.MybatisUtils; +import org.apache.ibatis.annotations.Param; + +import java.util.List; /** - * mapper 父类,注意这个类不要让 mybatis-plus 扫描到!! + * mapper 父类,在 MyBatis Plus 的 BaseMapper 的基础上拓展,提供更多功能。注意这个类不要让 mybatis-plus 扫描到!! * @author 陌溪 * @date 2020年12月31日21:32:33 */ public interface SuperMapper extends BaseMapper { - // 这里可以放一些公共的方法 + /** + * 查询分页 + */ + default PageVO selectPage(PageDTO pageDTO, @Param("ew") Wrapper queryWrapper) { + // MyBatis Plus 分页查询 + IPage myBatisPage = MybatisUtils.buildPage(pageDTO); + selectPage(myBatisPage, queryWrapper); + // 转换返回值 + return new PageVO<>(myBatisPage.getRecords(), myBatisPage.getTotal(), myBatisPage.getSize()); + } + + /** + * 查询分页 + * + * @param d 实体类参数对接 + * @param selectColumns 查询返回的列 + */ + default PageVO selectPage(D d, SFunction... selectColumns) { + // 构造分页,不能强制转 pageDTO,否则如果没有继承的话,会报错 + PageDTO pageDTO = d instanceof PageDTO ? (PageDTO) d : null; + IPage myBatisPage = MybatisUtils.buildPage(pageDTO); + // 查询数据 + selectPage(myBatisPage, buildQueryWrapper(d, selectColumns)); + // 转换返回值 + return new PageVO<>(myBatisPage.getRecords(), myBatisPage.getTotal(), myBatisPage.getSize()); + } + + /** + * 查询列表 + * + * @param d 实体类参数对接 + * @param selectColumns 查询返回的列 + */ + default List selectList(D d, SFunction... selectColumns) { + return selectList(buildQueryWrapper(d, selectColumns)); + } + + /** + * 查询单条 + * + * @param d 实体类参数对接 + */ + default T selectOne(D d) { + return selectOne(buildQueryWrapper(d)); + } + + /** + * 查询总记录数 + * + * @param d 实体类参数对接 + */ + default Long selectCount(D d) { + return selectCount(buildQueryWrapper(d)).longValue(); + } + + /** + * 构建 Wrapper 查询条件 + * + * @param d DTO 实体参数对象 + * @param selectColumns 查询返回的列 + * @return 查询构造器 + */ + default QueryWrapperPlus buildQueryWrapper(D d, SFunction... selectColumns) { + Class[] typeArguments = GenericTypeUtils.resolveTypeArguments(ClassUtils.getUserClass(this.getClass()), SuperMapper.class); + Class entityClass = null == typeArguments ? null : (Class) typeArguments[0]; + return new QueryWrapperPlus().buildQueryWrapper(entityClass, d, selectColumns); + } + + } diff --git a/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/page/dto/PageDTO.java b/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/page/dto/PageDTO.java new file mode 100644 index 000000000..63927fb53 --- /dev/null +++ b/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/page/dto/PageDTO.java @@ -0,0 +1,42 @@ +package com.moxi.mougblog.base.mybatis.page.dto; +import com.moxi.mougblog.base.mybatis.plugin.annotation.Query; +import lombok.Data; + +import java.io.Serializable; + +/** + * 分页对象 + * + * @author geshanzsq + * @date 2022/3/27 + */ +@Data +public class PageDTO implements Serializable { + + private static final Long serialVersionUID = 1L; + + /** + * 每页显示记录数 + */ + @Query(ignore = true) + private Long pageSize; + + /** + * 起始页 + */ + @Query(ignore = true) + private Long currentPage; + + /** + * 排序列,多个用逗号分开 + */ + @Query(ignore = true) + private String orderColumn; + + /** + * 排序类型(asc 或 desc),多个用逗号分开 + */ + @Query(ignore = true) + private String orderType; + +} diff --git a/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/page/util/PageUtils.java b/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/page/util/PageUtils.java new file mode 100644 index 000000000..322719a78 --- /dev/null +++ b/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/page/util/PageUtils.java @@ -0,0 +1,54 @@ +package com.moxi.mougblog.base.mybatis.page.util; + +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.moxi.mougblog.base.mybatis.page.dto.PageDTO; +import com.moxi.mougblog.base.mybatis.page.vo.PageVO; +import com.moxi.mougblog.base.mybatis.property.PageProperty; + +import java.util.List; + +/** + * 分页工具类 + * + * @author geshanzsq + * @date 2022/3/27 + */ +public class PageUtils { + + /** + * 开始分页 + */ + public static void startPage(PageDTO pageDTO) { + startPage(pageDTO.getCurrentPage(), pageDTO.getPageSize()); + } + + /** + * 开始分页 + * @param pageNum 起始页 + * @param pageSize 分页记录数 + */ + public static void startPage(Long pageNum, Long pageSize) { + if (pageNum == null) { + pageNum = 1L; + } + if (pageSize == null) { + pageSize = PageProperty.defaultPageSize; + } + // 如果超过最大分页数,则设置为最大分页数 + if (pageSize > PageProperty.maxPageSize) { + pageSize = PageProperty.maxPageSize; + } + PageHelper.startPage(pageNum.intValue(), pageSize.intValue()); + } + + + /** + * 获取分页信息 + */ + public static PageVO getPage(List list) { + PageInfo pageInfo = new PageInfo(list); + return new PageVO(list, pageInfo.getTotal(), pageInfo.getSize()); + } + +} diff --git a/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/page/vo/PageVO.java b/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/page/vo/PageVO.java new file mode 100644 index 000000000..1bd98464a --- /dev/null +++ b/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/page/vo/PageVO.java @@ -0,0 +1,38 @@ +package com.moxi.mougblog.base.mybatis.page.vo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +/** + * 分页对象 + * + * @author geshanzsq + * @date 2022/3/27 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class PageVO implements Serializable { + + private static final Long serialVersionUID = 1L; + + /** + * 数据列表 + */ + private List records; + + /** + * 总记录数 + */ + private long total; + + /** + * 每页显示记录数 + */ + private long size; + +} diff --git a/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/plugin/annotation/Query.java b/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/plugin/annotation/Query.java new file mode 100644 index 000000000..e5725b22e --- /dev/null +++ b/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/plugin/annotation/Query.java @@ -0,0 +1,39 @@ +package com.moxi.mougblog.base.mybatis.plugin.annotation; + +import com.moxi.mougblog.base.mybatis.plugin.enums.QueryWay; + +import java.lang.annotation.*; + +/** + * 查询注解 + * + * @author geshanzsq + * @date 2022/11/4 + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Query { + + /** + * 查询方式,默认为相等 + */ + QueryWay value() default QueryWay.EQ; + + /** + * 属性名,如果当前属性名与 PO 不一致,可指定 PO 的属性名 + */ + String fieldName() default ""; + + /** + * 是否忽略查询,如果当前属性不需要查询,则可设置为 true + */ + boolean ignore() default false; + + /** + * 是否空查询,当为空时,是否依旧查询,默认不需要查询 + */ + boolean empty() default false; + + +} diff --git a/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/plugin/constant/FieldConstant.java b/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/plugin/constant/FieldConstant.java new file mode 100644 index 000000000..b5325dc83 --- /dev/null +++ b/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/plugin/constant/FieldConstant.java @@ -0,0 +1,21 @@ +package com.moxi.mougblog.base.mybatis.plugin.constant; + +/** + * 字段常量 + * + * @author geshanzsq + * @date 2022/8/7 + */ +public class FieldConstant { + + /** + * 排序列,多个用逗号分开 + */ + public static final String ORDER_COLUMN = "orderColumn"; + + /** + * 排序类型(asc 或 desc),多个用逗号分开 + */ + public static final String ORDER_TYPE = "orderType"; + +} diff --git a/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/plugin/enums/QueryWay.java b/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/plugin/enums/QueryWay.java new file mode 100644 index 000000000..34c4a90fd --- /dev/null +++ b/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/plugin/enums/QueryWay.java @@ -0,0 +1,71 @@ +package com.moxi.mougblog.base.mybatis.plugin.enums; + +/** + * 查询方式枚举 + * + * @author geshanzsq + * @date 2022/11/4 + */ +public enum QueryWay { + + /** + * 等于 + */ + EQ, + + /** + * 不等于 + */ + NE, + + /** + * 大于 + */ + GT, + + /** + * 大于等于 + */ + GE, + + /** + * 小于 + */ + LT, + + /** + * 小于等于 + */ + LE, + + /** + * 模糊 + */ + LIKE, + + /** + * 不模糊 + */ + NOT_LIKE, + + /** + * 左模糊 + */ + LIKE_LEFT, + + /** + * 右模糊 + */ + LIKE_RIGHT, + + /** + * 包含 + */ + IN, + + /** + * 不包含 + */ + NOT_IN + +} diff --git a/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/plugin/query/LambdaQueryWrapperPlus.java b/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/plugin/query/LambdaQueryWrapperPlus.java new file mode 100644 index 000000000..7e0a76827 --- /dev/null +++ b/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/plugin/query/LambdaQueryWrapperPlus.java @@ -0,0 +1,115 @@ +package com.moxi.mougblog.base.mybatis.plugin.query; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; +import com.moxi.mogublog.utils.StringUtils; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; + +/** + * 扩展 LambdaQueryWrapper 类 + * 添加 xxxIf 方法,当值不存在的时候,不要拼接条件 + * + * @author geshanzsq + * @date 2022/3/27 + */ +public class LambdaQueryWrapperPlus extends LambdaQueryWrapper { + + /** + * 模糊查询 + */ + public LambdaQueryWrapperPlus likeIf(SFunction column, String value) { + return StringUtils.isBlank(value) ? this : like(column, value); + } + + @Override + public LambdaQueryWrapperPlus like(SFunction column, Object value) { + return (LambdaQueryWrapperPlus) super.like(column, value); + } + + /** + * 相等 + */ + public LambdaQueryWrapperPlus eqIf(SFunction column, Object value) { + return StringUtils.isNullBlank(value) ? this : eq(column, value); + } + + @Override + public LambdaQueryWrapperPlus eq(SFunction column, Object value) { + return (LambdaQueryWrapperPlus) super.eq(column, value); + } + + /** + * 包含 + */ + public LambdaQueryWrapperPlus inIf(SFunction column, Collection values) { + return CollectionUtils.isEmpty(values) ? this : in(column, values); + } + + @Override + public LambdaQueryWrapperPlus in(SFunction column, Collection values) { + return (LambdaQueryWrapperPlus) super.in(column, values); + } + + /** + * 不包含 + */ + public LambdaQueryWrapperPlus notInIf(SFunction column, Collection values) { + return CollectionUtils.isEmpty(values) ? this : notIn(column, values); + } + + @Override + public LambdaQueryWrapperPlus notIn(SFunction column, Collection values) { + return (LambdaQueryWrapperPlus) super.notIn(column, values); + } + + /** + * 小于 + */ + public LambdaQueryWrapperPlus ltIf(SFunction column, Object value) { + return StringUtils.isNullBlank(value) ? this : lt(column, value); + } + + @Override + public LambdaQueryWrapperPlus lt(SFunction column, Object value) { + return (LambdaQueryWrapperPlus) super.lt(column, value); + } + + /** + * 小于等于 + */ + public LambdaQueryWrapperPlus leIf(SFunction column, Object value) { + return StringUtils.isNullBlank(value) ? this : le(column, value); + } + + @Override + public LambdaQueryWrapperPlus le(SFunction column, Object value) { + return (LambdaQueryWrapperPlus) super.le(column, value); + } + + /** + * 大于 + */ + public LambdaQueryWrapperPlus gtIf(SFunction column, Object value) { + return StringUtils.isNullBlank(value) ? this : gt(column, value); + } + + @Override + public LambdaQueryWrapperPlus gt(SFunction column, Object value) { + return (LambdaQueryWrapperPlus) super.gt(column, value); + } + + /** + * 大于等于 + */ + public LambdaQueryWrapperPlus geIf(SFunction column, Object value) { + return StringUtils.isNullBlank(value) ? this : ge(column, value); + } + + @Override + public LambdaQueryWrapperPlus ge(SFunction column, Object value) { + return (LambdaQueryWrapperPlus) super.ge(column, value); + } + +} diff --git a/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/plugin/query/QueryWrapperPlus.java b/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/plugin/query/QueryWrapperPlus.java new file mode 100644 index 000000000..2fab8c930 --- /dev/null +++ b/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/plugin/query/QueryWrapperPlus.java @@ -0,0 +1,269 @@ +package com.moxi.mougblog.base.mybatis.plugin.query; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.enums.SqlKeyword; +import com.baomidou.mybatisplus.core.metadata.TableInfo; +import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; +import com.baomidou.mybatisplus.core.toolkit.ClassUtils; +import com.baomidou.mybatisplus.core.toolkit.ReflectionKit; +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; +import com.moxi.mogublog.utils.StringUtils; +import com.moxi.mougblog.base.exception.exceptionType.QueryException; +import com.moxi.mougblog.base.mybatis.plugin.annotation.Query; +import com.moxi.mougblog.base.mybatis.plugin.constant.FieldConstant; +import com.moxi.mougblog.base.mybatis.plugin.enums.QueryWay; +import com.moxi.mougblog.base.result.ResultCode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.Field; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 扩展 QueryWrapper 类,提供更多功能 + * + * @author geshanzsq + * @date 2022/11/4 + */ +public class QueryWrapperPlus extends QueryWrapper { + + private static final Logger log = LoggerFactory.getLogger(QueryWrapperPlus.class); + + /** + * 排序字段分割标识 + */ + private static final String ORDER_BY_COLUMN_SPLIT = ","; + + /** + * 构建 Wrapper 查询条件 + * + * @param clazz PO 实体类 + * @param d DTO 实体参数对象 + * @param selectColumns 查询返回的列 + * @return 查询构造器 + */ + public QueryWrapperPlus buildQueryWrapper(Class clazz, D d, SFunction... selectColumns) { + QueryWrapperPlus queryWrapper = new QueryWrapperPlus(); + // 构建指定返回的列 + queryWrapper.lambda().select(selectColumns); + if (d == null) { + return queryWrapper; + } + + // 获取 T 属性和列名 + TableInfo tableInfo = TableInfoHelper.getTableInfo(clazz); + if (tableInfo == null) { + log.error("没有找到数据表对应的实体类,当前传入的 Clazz:{}", clazz); + throw new QueryException(ResultCode.FAILED.getMsg()); + } + + // T 属性和列名对应关系 + Map propertyColumnMap = new HashMap<>(tableInfo.getFieldList().size()); + tableInfo.getFieldList().forEach(table -> { + propertyColumnMap.put(table.getProperty(), table.getColumn()); + }); + // 主键不在 fieldList 里,需单独获取 + if (StringUtils.isNotBlank(tableInfo.getKeyProperty())) { + propertyColumnMap.put(tableInfo.getKeyProperty(), tableInfo.getKeyColumn()); + } + + // 获取 d 属性 + List fieldList = ReflectionKit.getFieldList(ClassUtils.getUserClass(d.getClass())); + for (Field field : fieldList) { + field.setAccessible(true); + // 获取查询注解 + Query query = field.getAnnotation(Query.class); + + // 获取查询属性名称 + String fieldName = getQueryFieldName(query, field); + // 是否忽略查询 + if (query != null && query.ignore()) { + continue; + } + + // 校验查询属性是否在 T 实体类 + verifyQueryFieldNameExist(fieldName, propertyColumnMap); + + // 获取查询值 + Object value = getFieldValue(field, d); + + // 如果为空并且不需要空查询(默认不需要空查询),则跳过此属性查询 + if (StringUtils.isNullBlank(value) && (query == null || !query.empty())) { + continue; + } + + // 获取查询属性对应的列 + String column = propertyColumnMap.get(fieldName); + // 构造查询条件 + buildQueryCondition(queryWrapper, query, column, value); + } + + buildOrderByCondition(queryWrapper, propertyColumnMap, fieldList, d); + + return queryWrapper; + } + + /** + * 获取查询属性名称 + */ + private String getQueryFieldName(Query query, Field field) { + return query != null && StringUtils.isNotBlank(query.fieldName()) ? query.fieldName() : field.getName(); + } + + /** + * 校验查询属性是否在 T 实体类 + */ + private void verifyQueryFieldNameExist(String fieldName, Map propertyColumnMap) { + if (!propertyColumnMap.containsKey(fieldName)) { + String message = StringUtils.format("查询条件字段:{fieldName} 不存在", fieldName); + throw new QueryException(message); + } + } + + /** + * 获取属性值 + */ + private Object getFieldValue(Field field, D d) { + if (field == null) { + return null; + } + Object value = null; + try { + value = field.get(d); + } catch (IllegalAccessException e) { + e.printStackTrace(); + throw new QueryException(ResultCode.FAILED.getMsg()); + } + return value; + } + + /** + * 构建查询条件 + * + * @param queryWrapper 查询构造器 + * @param query 查询注解 + * @param column 列名称 + * @param value 值 + */ + private void buildQueryCondition(QueryWrapperPlus queryWrapper, Query query, String column, Object value) { + // 默认为相等 + if (query == null || query.value() == null) { + queryWrapper.eq(column, value); + return; + } + // 查询方式 + QueryWay queryWay = query.value(); + switch (queryWay) { + case EQ: { + queryWrapper.eq(column, value); + break; + } + case NE: { + queryWrapper.ne(column, value); + break; + } + case GT: { + queryWrapper.gt(column, value); + break; + } + case GE: { + queryWrapper.ge(column, value); + break; + } + case LT: { + queryWrapper.lt(column, value); + break; + } + case LE: { + queryWrapper.le(column, value); + break; + } + case LIKE: { + queryWrapper.like(column, value); + break; + } + case NOT_LIKE: { + queryWrapper.notLike(column, value); + break; + } + case LIKE_LEFT: { + queryWrapper.likeLeft(column, value); + break; + } + case LIKE_RIGHT: { + queryWrapper.likeRight(column, value); + break; + } + case IN: { + if (value instanceof Collection) { + Collection coll = (Collection) value; + queryWrapper.in(column, coll); + } else { + queryWrapper.in(column, value); + } + break; + } + case NOT_IN: { + if (value instanceof Collection) { + Collection coll = (Collection) value; + queryWrapper.notIn(column, coll); + } else { + queryWrapper.notIn(column, value); + } + break; + } + default: { + queryWrapper.eq(column, value); + } + } + } + + /** + * 构造排序 + * + * @param queryWrapper 查询构造器 + * @param propertyColumnMap T 属性和列名 + * @param d 参数 + * @param fieldList d 属性列表 + */ + private void buildOrderByCondition(QueryWrapperPlus queryWrapper, Map propertyColumnMap, + List fieldList, D d) { + // 排序列 + Field orderColumnField = fieldList.stream().filter(f -> FieldConstant.ORDER_COLUMN.equals(f.getName())).findFirst().orElse(null); + // 如果排序字段为空,或者不是 String 类型,不进行排序 + Object orderColumnObj = getFieldValue(orderColumnField, d); + if (!(orderColumnObj instanceof String) || StringUtils.isNullBlank(orderColumnObj)) { + return; + } + + // 排序类型 + Field orderTypeField = fieldList.stream().filter(f -> FieldConstant.ORDER_TYPE.equals(f.getName())).findFirst().orElse(null); + Object orderTypeObj = getFieldValue(orderTypeField, d); + + String[] orderColumns = orderColumnObj.toString().split(ORDER_BY_COLUMN_SPLIT); + String[] orderTypes = orderTypeObj == null ? new String[] {} : orderTypeObj.toString().split(ORDER_BY_COLUMN_SPLIT); + + // 构造排序 + for (int i = 0; i < orderColumns.length; i++) { + String orderColumn = orderColumns[i]; + if (StringUtils.isBlank(orderColumn)) { + continue; + } + // 校验排序字段是否存在 + String column = propertyColumnMap.get(orderColumn); + if (StringUtils.isBlank(column)) { + String message = StringUtils.format("排序字段:{},不存在", orderColumn); + throw new QueryException(message); + } + + // 是否升序排序 + boolean isAsc = i < orderTypes.length ? SqlKeyword.ASC.getSqlSegment().equalsIgnoreCase(orderTypes[i]) : true; + queryWrapper.orderBy(true, isAsc, column); + } + + } + +} diff --git a/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/property/PageProperty.java b/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/property/PageProperty.java new file mode 100644 index 000000000..f6b80b454 --- /dev/null +++ b/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/property/PageProperty.java @@ -0,0 +1,36 @@ +package com.moxi.mougblog.base.mybatis.property; + +import lombok.Getter; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; + +/** + * 分页配置 + * + * @author geshanzsq + * @date 2022/3/27 + */ +@Getter +@Configuration +public class PageProperty { + + /** + * 默认分页记录数 + */ + public static Long defaultPageSize = 10L; + + /** + * 最大分页记录数 + */ + public static Long maxPageSize = 200L; + + @Value("${page.default-page-size}") + public void setDefaultPageSize(Long defaultPageSize) { + PageProperty.defaultPageSize = defaultPageSize; + } + + @Value("${page.max-page-size}") + public void setMaxPageSize(Long maxPageSize) { + PageProperty.maxPageSize = maxPageSize; + } +} diff --git a/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/reflect/GenericTypeUtils.java b/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/reflect/GenericTypeUtils.java new file mode 100644 index 000000000..2078a2c4b --- /dev/null +++ b/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/reflect/GenericTypeUtils.java @@ -0,0 +1,24 @@ +package com.moxi.mougblog.base.mybatis.reflect; + +/** + * 来源于 MyBatis Plus 更高版本 + * + * @author geshanzsq + * @date 2024/6/4 + */ +public class GenericTypeUtils { + + private static IGenericTypeResolver GENERIC_TYPE_RESOLVER; + + public GenericTypeUtils() { + } + + public static Class[] resolveTypeArguments(final Class clazz, final Class genericIfc) { + return null == GENERIC_TYPE_RESOLVER ? SpringReflectionHelper.resolveTypeArguments(clazz, genericIfc) : GENERIC_TYPE_RESOLVER.resolveTypeArguments(clazz, genericIfc); + } + + public static void setGenericTypeResolver(IGenericTypeResolver genericTypeResolver) { + GENERIC_TYPE_RESOLVER = genericTypeResolver; + } + +} diff --git a/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/reflect/IGenericTypeResolver.java b/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/reflect/IGenericTypeResolver.java new file mode 100644 index 000000000..ed24d5353 --- /dev/null +++ b/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/reflect/IGenericTypeResolver.java @@ -0,0 +1,13 @@ +package com.moxi.mougblog.base.mybatis.reflect; + +/** + * 来源于 MyBatis Plus 更高版本 + * + * @author geshanzsq + * @date 2024/6/4 + */ +public interface IGenericTypeResolver { + + Class[] resolveTypeArguments(final Class clazz, final Class genericIfc); + +} diff --git a/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/reflect/SpringReflectionHelper.java b/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/reflect/SpringReflectionHelper.java new file mode 100644 index 000000000..e61e551de --- /dev/null +++ b/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/reflect/SpringReflectionHelper.java @@ -0,0 +1,20 @@ +package com.moxi.mougblog.base.mybatis.reflect; + +import org.springframework.core.GenericTypeResolver; + +/** + * 来源于 MyBatis Plus 更高版本 + * + * @author geshanzsq + * @date 2024/6/4 + */ +public class SpringReflectionHelper { + + public SpringReflectionHelper() { + } + + public static Class[] resolveTypeArguments(Class clazz, Class genericIfc) { + return GenericTypeResolver.resolveTypeArguments(clazz, genericIfc); + } + +} diff --git a/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/util/MybatisUtils.java b/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/util/MybatisUtils.java new file mode 100644 index 000000000..cd03344d6 --- /dev/null +++ b/mogu_base/src/main/java/com/moxi/mougblog/base/mybatis/util/MybatisUtils.java @@ -0,0 +1,48 @@ +package com.moxi.mougblog.base.mybatis.util; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.moxi.mougblog.base.mybatis.page.dto.PageDTO; +import com.moxi.mougblog.base.mybatis.property.PageProperty; + +/** + * MyBatis 工具类 + * + * @author geshanzsq + * @date 2022/6/26 + */ +public class MybatisUtils { + + /** + * 构建分页 + */ + public static Page buildPage(PageDTO pageDTO) { + Long pageNum = null; + Long pageSize = null; + if (pageDTO != null) { + pageNum = pageDTO.getCurrentPage(); + pageSize = pageDTO.getPageSize(); + } + return buildPage(pageNum, pageSize); + } + + /** + * 构建分页 + */ + public static Page buildPage(Long pageNum, Long pageSize) { + // 如果为空,则设置默认值 + if (pageNum == null) { + pageNum = 1L; + } + if (pageSize == null) { + pageSize = PageProperty.defaultPageSize; + } + + // 如果超过最大分页数,则设置为最大分页数 + if (pageSize > PageProperty.maxPageSize) { + pageSize = PageProperty.maxPageSize; + } + Page page = new Page<>(pageNum, pageSize); + return page; + } + +} diff --git a/mogu_base/src/main/java/com/moxi/mougblog/base/service/SuperService.java b/mogu_base/src/main/java/com/moxi/mougblog/base/service/SuperService.java index d4363456b..aaaf64b06 100644 --- a/mogu_base/src/main/java/com/moxi/mougblog/base/service/SuperService.java +++ b/mogu_base/src/main/java/com/moxi/mougblog/base/service/SuperService.java @@ -1,9 +1,15 @@ package com.moxi.mougblog.base.service; +import com.baomidou.mybatisplus.core.toolkit.ReflectionKit; +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; import com.baomidou.mybatisplus.extension.service.IService; +import com.moxi.mougblog.base.mybatis.page.vo.PageVO; +import com.moxi.mougblog.base.mybatis.plugin.query.QueryWrapperPlus; + +import java.util.List; /** - * Service父类 + * Service父类,在 MyBatis Plus 的 IService 的基础上拓展,提供更多功能 * * @param * @author 陌溪 @@ -11,4 +17,70 @@ */ public interface SuperService extends IService { + /** + * 查询分页 + * + * @param d 实体类参数对接 + * @param selectColumns 查询返回的列 + */ + PageVO page(D d, SFunction... selectColumns); + + /** + * 查询列表 + * + * @param d 实体类参数对接 + * @param selectColumns 查询返回的列 + */ + default List list(D d, SFunction... selectColumns) { + return list(buildQueryWrapper(d, selectColumns)); + } + + /** + * 查询单条 + * + * @param d 实体类参数对接 + */ + default T getOne(D d) { + return getOne(buildQueryWrapper(d)); + } + + /** + * 查询单条 + * + * @param d 实体类参数对接 + * @param throwEx 有多个结果是否抛出异常 + */ + default T getOne(D d, boolean throwEx) { + return getOne(buildQueryWrapper( d), throwEx); + } + + /** + * 查询总记录数 + * + * @param d 实体类参数对接 + */ + default Long count(D d) { + return (long) count(buildQueryWrapper(d)); + } + + /** + * 构建 Wrapper 查询条件 + * + * @param d DTO 实体参数对象 + * @param selectColumns 查询返回的列 + * @return 查询构造器 + */ + default QueryWrapperPlus buildQueryWrapper(D d, SFunction... selectColumns) { + return new QueryWrapperPlus().buildQueryWrapper(getEntityClass(), d, selectColumns); + } + + /** + * 获取当前T 类型 Class + * + * @return + */ + default Class getEntityClass() { + return (Class) ReflectionKit.getSuperClassGenericType(this.getClass(), 1); + } + } diff --git a/mogu_base/src/main/java/com/moxi/mougblog/base/serviceImpl/SuperServiceImpl.java b/mogu_base/src/main/java/com/moxi/mougblog/base/serviceImpl/SuperServiceImpl.java index d366ab2e1..988301bb9 100644 --- a/mogu_base/src/main/java/com/moxi/mougblog/base/serviceImpl/SuperServiceImpl.java +++ b/mogu_base/src/main/java/com/moxi/mougblog/base/serviceImpl/SuperServiceImpl.java @@ -1,8 +1,11 @@ package com.moxi.mougblog.base.serviceImpl; +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.moxi.mougblog.base.mapper.SuperMapper; +import com.moxi.mougblog.base.mybatis.page.vo.PageVO; import com.moxi.mougblog.base.service.SuperService; +import org.springframework.beans.factory.annotation.Autowired; /** @@ -15,4 +18,18 @@ public class SuperServiceImpl, T> extends ServiceImpl implements SuperService { + @Autowired + private M baseMapper; + + /** + * 查询分页 + * + * @param d 实体类参数对接 + * @param selectColumns 查询返回的列 + */ + @Override + public PageVO page(D d, SFunction... selectColumns) { + return baseMapper.selectPage(d, selectColumns); + } + } diff --git a/pom.xml b/pom.xml index 548abac0c..edd3f9ac6 100644 --- a/pom.xml +++ b/pom.xml @@ -47,6 +47,7 @@ 3.0.2 2.2.4.RELEASE 2.2.5.RELEASE + 1.4.1