From 2c5772d09d52a646ebd30914b4d7a93f08413cdf Mon Sep 17 00:00:00 2001 From: bjdys Date: Fri, 20 Aug 2021 14:32:38 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E9=80=89=E6=8B=A9=E6=98=A0?= =?UTF-8?q?=E5=B0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/metadata/MPJTableFieldInfo.java | 39 +- .../yulichang/annotation/MPJMapping.java | 43 +- .../yulichang/base/mapper/MPJDeepMapper.java | 251 +++++++-- .../base/service/MPJDeepService.java | 506 ++++++++++++++++-- .../yulichang/injector/MPJSqlInjector.java | 14 +- 5 files changed, 718 insertions(+), 135 deletions(-) diff --git a/src/main/java/com/baomidou/mybatisplus/core/metadata/MPJTableFieldInfo.java b/src/main/java/com/baomidou/mybatisplus/core/metadata/MPJTableFieldInfo.java index 5b23ed1..3aef77c 100644 --- a/src/main/java/com/baomidou/mybatisplus/core/metadata/MPJTableFieldInfo.java +++ b/src/main/java/com/baomidou/mybatisplus/core/metadata/MPJTableFieldInfo.java @@ -15,7 +15,6 @@ import lombok.ToString; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; -import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; @@ -40,6 +39,10 @@ public class MPJTableFieldInfo { * 属性 */ private Field field; + /** + * 属性名 + */ + private String property; /** * 数据结构是否是Map或者List */ @@ -67,7 +70,7 @@ public class MPJTableFieldInfo { /** * 映射实体类 */ - private final Class joinClass; + private Class joinClass; /** * 映射属性名 */ @@ -102,15 +105,17 @@ public class MPJTableFieldInfo { /** * 初始化关联字段信息 */ - public MPJTableFieldInfo(Class entityType, MPJMapping mapping, Field field1) { - initField(field1); + public MPJTableFieldInfo(Class entityType, MPJMapping mapping, Field field) { + initField(field); + if (mapping.tag() != Object.class) { + this.joinClass = mapping.tag(); + } this.entityType = entityType; - this.joinClass = mapping.tag(); this.isThrowExp = mapping.isThrowExp(); this.thisMapKey = StringUtils.isBlank(mapping.thisMapKey()) ? null : mapping.thisMapKey(); this.joinMapKey = StringUtils.isBlank(mapping.joinMapKsy()) ? null : mapping.joinMapKsy(); this.wrapper = new MPJMappingWrapper(mapping); - if (this.isCollection && this.field.getType() != List.class && this.field.getType() != ArrayList.class) { + if (this.isCollection && !List.class.isAssignableFrom(this.field.getType())) { throw new MPJException("对多关系的数据结构目前只支持 暂不支持其他Collection实现 " + this.field.getType().getTypeName()); } if (StringUtils.isNotBlank(mapping.joinField())) { @@ -132,6 +137,7 @@ public class MPJTableFieldInfo { private void initField(Field field) { field.setAccessible(true); this.field = field; + this.property = field.getName(); this.isCollection = Collection.class.isAssignableFrom(field.getType()); if (Map.class.isAssignableFrom(field.getType())) { @@ -149,6 +155,15 @@ public class MPJTableFieldInfo { this.fieldIsMap = false; } } + + if (List.class.isAssignableFrom(field.getType())) { + if (field.getGenericType() instanceof ParameterizedType) { + ParameterizedType t = (ParameterizedType) field.getGenericType(); + this.joinClass = (Class) t.getActualTypeArguments()[0]; + } + } else { + this.joinClass = field.getType(); + } } @SuppressWarnings("ConstantConditions") @@ -269,28 +284,28 @@ public class MPJTableFieldInfo { } public static void bind(MPJTableFieldInfo fieldInfo, T i, List data) { - if (!fieldInfo.isCollection()) { + if (fieldInfo.isCollection()) { + fieldInfo.fieldSet(i, data); + } else { if (data.size() > 1 && fieldInfo.isThrowExp()) { throw new MPJException("Expected one result (or null) to be returned by select, but found: " + data.size() + " , " + fieldInfo.getField().getName()); } else { fieldInfo.fieldSet(i, data.stream().findFirst().orElse(null)); } - } else { - fieldInfo.fieldSet(i, data); } } public static void bindMap(MPJTableFieldInfo fieldInfo, Map i, List data) { - if (!fieldInfo.isCollection()) { + if (fieldInfo.isCollection()) { + i.put(fieldInfo.getField().getName(), data); + } else { if (data.size() > 1 && fieldInfo.isThrowExp()) { throw new MPJException("Expected one result (or null) to be returned by select, but found: " + data.size() + " , " + fieldInfo.getField().getName()); } else { i.put(fieldInfo.getField().getName(), data.stream().findFirst().orElse(null)); } - } else { - i.put(fieldInfo.getField().getName(), data); } } diff --git a/src/main/java/com/github/yulichang/annotation/MPJMapping.java b/src/main/java/com/github/yulichang/annotation/MPJMapping.java index 8b381e9..3cec144 100644 --- a/src/main/java/com/github/yulichang/annotation/MPJMapping.java +++ b/src/main/java/com/github/yulichang/annotation/MPJMapping.java @@ -15,62 +15,63 @@ import java.lang.annotation.*; public @interface MPJMapping { /** - * 关联的数据库实体类 + * 关联的数据库实体类
+ * 默认获取此注解所对应的类 */ - Class tag(); + Class tag() default Object.class; /** - * 当前类的关联的字段名称 (是实体类字段名称而不是数据库字段名称) + * 当前类的关联的字段名称 (是实体类字段名称而不是数据库字段名称)
* 默认获取当前类上定义的主键 @TableId */ String thisField() default ""; /** - * 关联类的字段名称 (是实体类字段名称而不是数据库字段名称) + * 关联类的字段名称 (是实体类字段名称而不是数据库字段名称)
* 默认获取关联类上定义的主键 @TableId */ String joinField() default ""; /** - * 一对一查询时 如果查询到多条记录是否抛出异常 - * true 抛出异常 - * false 不抛异常,获取列表第一条数据 + * 一对一查询时 如果查询到多条记录是否抛出异常
+ * true 抛出异常
+ * false 不抛异常,获取列表第一条数据
*/ boolean isThrowExp() default true; /** - * 针对查询结果map的时候使用 - * 默认为thisField对应的数据库列名 + * 针对查询结果map的时候使用
+ * 默认为thisField对应的数据库列名
*

- * 如果此类是以map方式查询的 - * 并且查询出来的map的key不是thisField对应的数据库列名就需要设置 + * 如果此类是以map方式查询的
+ * 并且查询出来的map的key不是thisField对应的数据库列名就需要设置
*/ String thisMapKey() default ""; /** - * isMap为true时生效 - * 针对查询结果map的时候使用 - * 默认为joinField对应的数据库列名 + * isMap为true时生效
+ * 针对查询结果map的时候使用
+ * 默认为joinField对应的数据库列名
*

- * 如果此类是以map方式查询的 - * 并且查询出来的map的key不是thisField对应的数据库列名就需要设置 + * 如果此类是以map方式查询的
+ * 并且查询出来的map的key不是thisField对应的数据库列名就需要设置
*/ String joinMapKsy() default ""; /** - * 映射表查询条件之 select + * 映射表查询条件之 select
* 等效于 Wrappers.query().select(xxx); */ String select() default ""; /** - * 映射表查询条件之 first + * 映射表查询条件之 first
* 等效于 Wrappers.query().first(xxx); */ String first() default ""; /** - * 映射表查询条件之 apply + * 映射表查询条件之 apply
* 等效于 Wrappers.query().apply(xxx); */ MPJMappingApply[] apply() default {}; @@ -81,8 +82,8 @@ public @interface MPJMapping { MPJMappingCondition[] condition() default {}; /** - * 映射表查询条件之 last - * 建议不要在这使用分页语句,会导致关联查的时候查询不全 + * 映射表查询条件之 last
+ * 建议不要在这使用分页语句,会导致关联查的时候查询不全
* 等效于 Wrappers.query().last(xxx); */ String last() default ""; diff --git a/src/main/java/com/github/yulichang/base/mapper/MPJDeepMapper.java b/src/main/java/com/github/yulichang/base/mapper/MPJDeepMapper.java index cf89a4e..6f9cc69 100644 --- a/src/main/java/com/github/yulichang/base/mapper/MPJDeepMapper.java +++ b/src/main/java/com/github/yulichang/base/mapper/MPJDeepMapper.java @@ -6,30 +6,52 @@ import com.baomidou.mybatisplus.core.enums.SqlKeyword; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.metadata.*; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; -import com.baomidou.mybatisplus.core.toolkit.Constants; -import org.apache.ibatis.annotations.Param; +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; +import com.github.yulichang.toolkit.LambdaUtils; import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; /** * @author yulichang * @see BaseMapper */ -@SuppressWarnings("unused") +@SuppressWarnings({"unused", "unchecked"}) public interface MPJDeepMapper extends BaseMapper { /** - * 根据 ID 查询 + * 根据 ID 查询 并关联全部映射 * * @param id 主键ID */ default T selectByIdDeep(Serializable id) { - return queryMapping(selectById(id)); + return queryMapping(selectById(id), null); + } + + /** + * 根据 ID 查询 并关联指定映射 + *

+ * JDK 默认不推荐泛型数组,会引起 Java堆污染(Heap Pollution) + * + * @param id 主键ID + * @param property 需要关联的字段 + */ + default T selectByIdDeep(Serializable id, SFunction... property) { + return queryMapping(selectById(id), Arrays.asList(property)); + } + + /** + * 针对可变参数堆污染提供的重载 + * list为null或空,会查询全部映射关系 + *

+ * 例: selectByIdDeep(1, Arrays.asList(User::getId, ... )) + * + * @param id 主键ID + * @param property 需要关联的字段 + */ + default T selectByIdDeep(Serializable id, List> property) { + return queryMapping(selectById(id), property); } /** @@ -37,8 +59,33 @@ public interface MPJDeepMapper extends BaseMapper { * * @param idList 主键ID列表(不能为 null 以及 empty) */ - default List selectBatchIdsDeep(@Param(Constants.COLLECTION) Collection idList) { - return queryMapping(selectBatchIds(idList)); + default List selectBatchIdsDeep(Collection idList) { + return queryMapping(selectBatchIds(idList), null); + } + + /** + * 查询(根据ID 批量查询) + *

+ * JDK 默认不推荐泛型数组,会引起 Java堆污染(Heap Pollution) + * + * @param idList 主键ID列表(不能为 null 以及 empty) + * @param property 需要关联的字段 + */ + default List selectBatchIdsDeep(Collection idList, SFunction... property) { + return queryMapping(selectBatchIds(idList), Arrays.asList(property)); + } + + /** + * 针对可变参数堆污染提供的重载 + * list为null或空,会查询全部映射关系 + *

+ * 例: selectBatchIdsDeep(idList, Arrays.asList(User::getId, ... )) + * + * @param idList 主键ID列表(不能为 null 以及 empty) + * @param property 需要关联的字段 + */ + default List selectBatchIdsDeep(Collection idList, List> property) { + return queryMapping(selectBatchIds(idList), property); } /** @@ -46,8 +93,33 @@ public interface MPJDeepMapper extends BaseMapper { * * @param columnMap 表字段 map 对象 */ - default List selectByMapDeep(@Param(Constants.COLUMN_MAP) Map columnMap) { - return queryMapping(selectByMap(columnMap)); + default List selectByMapDeep(Map columnMap) { + return queryMapping(selectByMap(columnMap), null); + } + + /** + * 查询(根据 columnMap 条件) + *

+ * JDK 默认不推荐泛型数组,会引起 Java堆污染(Heap Pollution) + * + * @param columnMap 表字段 map 对象 + * @param property 需要关联的字段 + */ + default List selectByMapDeep(Map columnMap, SFunction... property) { + return queryMapping(selectByMap(columnMap), Arrays.asList(property)); + } + + /** + * 针对可变参数堆污染提供的重载 + * list为null或空,会查询全部映射关系 + *

+ * 例: selectByMapDeep(columnMap, Arrays.asList(User::getId, ... )) + * + * @param columnMap 表字段 map 对象 + * @param property 需要关联的字段 + */ + default List selectByMapDeep(Map columnMap, List> property) { + return queryMapping(selectByMap(columnMap), property); } /** @@ -55,8 +127,33 @@ public interface MPJDeepMapper extends BaseMapper { * * @param queryWrapper 实体对象封装操作类(可以为 null) */ - default T selectOneDeep(@Param(Constants.WRAPPER) Wrapper queryWrapper) { - return queryMapping(selectOne(queryWrapper)); + default T selectOneDeep(Wrapper queryWrapper) { + return queryMapping(selectOne(queryWrapper), null); + } + + /** + * 根据 entity 条件,查询一条记录 + *

+ * JDK 默认不推荐泛型数组,会引起 Java堆污染(Heap Pollution) + * + * @param queryWrapper 实体对象封装操作类(可以为 null) + * @param property 需要关联的字段 + */ + default T selectOneDeep(Wrapper queryWrapper, SFunction... property) { + return queryMapping(selectOne(queryWrapper), Arrays.asList(property)); + } + + /** + * 针对可变参数堆污染提供的重载 + * list为null或空,会查询全部映射关系 + *

+ * 例: selectOneDeep(queryWrapper, Arrays.asList(User::getId, ... )) + * + * @param queryWrapper 实体对象封装操作类(可以为 null) + * @param property 需要关联的字段 + */ + default T selectOneDeep(Wrapper queryWrapper, List> property) { + return queryMapping(selectOne(queryWrapper), property); } /** @@ -64,8 +161,33 @@ public interface MPJDeepMapper extends BaseMapper { * * @param queryWrapper 实体对象封装操作类(可以为 null) */ - default List selectListDeep(@Param(Constants.WRAPPER) Wrapper queryWrapper) { - return queryMapping(selectList(queryWrapper)); + default List selectListDeep(Wrapper queryWrapper) { + return queryMapping(selectList(queryWrapper), null); + } + + /** + * 根据 entity 条件,查询全部记录 + *

+ * JDK 默认不推荐泛型数组,会引起 Java堆污染(Heap Pollution) + * + * @param queryWrapper 实体对象封装操作类(可以为 null) + * @param property 需要关联的字段 + */ + default List selectListDeep(Wrapper queryWrapper, SFunction... property) { + return queryMapping(selectList(queryWrapper), Arrays.asList(property)); + } + + /** + * 针对可变参数堆污染提供的重载 + * list为null或空,会查询全部映射关系 + *

+ * 例: selectListDeep(queryWrapper, Arrays.asList(User::getId, ... )) + * + * @param queryWrapper 实体对象封装操作类(可以为 null) + * @param property 需要关联的字段 + */ + default List selectListDeep(Wrapper queryWrapper, List> property) { + return queryMapping(selectList(queryWrapper), property); } @@ -75,31 +197,68 @@ public interface MPJDeepMapper extends BaseMapper { * @param page 分页查询条件(可以为 RowBounds.DEFAULT) * @param queryWrapper 实体对象封装操作类(可以为 null) */ - default > E selectPageDeep(E page, @Param(Constants.WRAPPER) Wrapper queryWrapper) { + default > E selectPageDeep(E page, Wrapper queryWrapper) { E e = selectPage(page, queryWrapper); - queryMapping(e.getRecords()); + queryMapping(e.getRecords(), null); return e; } /** - * 查询映射关系 - * 对结果进行二次查询 - * 可以自行查询然后在通过此方法进行二次查询 + * 根据 entity 条件,查询全部记录(并翻页) + *

+ * JDK 默认不推荐泛型数组,会引起 Java堆污染(Heap Pollution) + * + * @param page 分页查询条件(可以为 RowBounds.DEFAULT) + * @param queryWrapper 实体对象封装操作类(可以为 null) + * @param property 需要关联的字段 + */ + default > E selectPageDeep(E page, Wrapper queryWrapper, SFunction... property) { + E e = selectPage(page, queryWrapper); + queryMapping(e.getRecords(), Arrays.asList(property)); + return e; + } + + /** + * 针对可变参数堆污染提供的重载 + * list为null或空,会查询全部映射关系 + *

+ * 例: selectPageDeep(page, queryWrapper, Arrays.asList(User::getId, ... )) + * + * @param page 分页查询条件(可以为 RowBounds.DEFAULT) + * @param queryWrapper 实体对象封装操作类(可以为 null) + * @param property 需要关联的字段 + */ + default > E selectPageDeep(E page, Wrapper queryWrapper, List> property) { + E e = selectPage(page, queryWrapper); + queryMapping(e.getRecords(), property); + return e; + } + + /** + * 查询映射关系
+ * 对结果进行二次查询
+ * 可以自行查询然后在通过此方法进行二次查询
+ * list为null或空,会查询全部映射关系
* * @param t 第一次查询结果 */ - default T queryMapping(T t) { + default T queryMapping(T t, List> property) { if (t == null) { return null; } MPJTableInfo tableInfo = MPJTableInfoHelper.getTableInfo(t.getClass()); if (tableInfo.isHasMapping()) { + boolean hasProperty = CollectionUtils.isNotEmpty(property); + List list = hasProperty ? property.stream().map(LambdaUtils::getName).collect( + Collectors.toList()) : null; for (MPJTableFieldInfo fieldInfo : tableInfo.getFieldList()) { - Object get = fieldInfo.thisFieldGet(t); - if (get != null) { - List o = (List) fieldInfo.getJoinMapper().mappingWrapperConstructor(fieldInfo.isFieldIsMap(), - SqlKeyword.EQ, fieldInfo.getJoinColumn(), get, fieldInfo); - MPJTableFieldInfo.bind(fieldInfo, t, o); + if (!hasProperty || list.contains(fieldInfo.getProperty())) { + Object get = fieldInfo.thisFieldGet(t); + if (get != null) { + List o = (List) fieldInfo.getJoinMapper().mappingWrapperConstructor(fieldInfo.isFieldIsMap(), + SqlKeyword.EQ, fieldInfo.getJoinColumn(), get, fieldInfo); + MPJTableFieldInfo.bind(fieldInfo, t, o); + } } } } @@ -107,30 +266,36 @@ public interface MPJDeepMapper extends BaseMapper { } /** - * 查询映射关系 - * 对结果进行二次查询 - * 可以自行查询然后在通过此方法进行二次查询 + * 查询映射关系
+ * 对结果进行二次查询
+ * 可以自行查询然后在通过此方法进行二次查询
+ * list为null或空,会查询全部映射关系
* * @param list 第一次查询结果 */ - default List queryMapping(List list) { + default List queryMapping(List list, List> property) { if (CollectionUtils.isEmpty(list)) { return list; } MPJTableInfo tableInfo = MPJTableInfoHelper.getTableInfo(list.get(0).getClass()); if (tableInfo.isHasMapping()) { + boolean hasProperty = CollectionUtils.isNotEmpty(property); + List listProperty = hasProperty ? property.stream().map(LambdaUtils::getName).collect( + Collectors.toList()) : null; for (MPJTableFieldInfo fieldInfo : tableInfo.getFieldList()) { - List itemList = list.stream().map(fieldInfo::thisFieldGet).collect(Collectors.toList()); - if (CollectionUtils.isNotEmpty(itemList)) { - List joinList = (List) fieldInfo.getJoinMapper().mappingWrapperConstructor( - fieldInfo.isFieldIsMap(), SqlKeyword.IN, fieldInfo.getJoinColumn(), itemList, fieldInfo); - list.forEach(i -> { - List data = joinList.stream().filter(j -> fieldInfo.joinFieldGet(j) - .equals(fieldInfo.thisFieldGet(i))).collect(Collectors.toList()); - MPJTableFieldInfo.bind(fieldInfo, i, data); - }); - } else { - list.forEach(i -> fieldInfo.fieldSet(i, new ArrayList<>())); + if (!hasProperty || listProperty.contains(fieldInfo.getProperty())) { + List itemList = list.stream().map(fieldInfo::thisFieldGet).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(itemList)) { + List joinList = (List) fieldInfo.getJoinMapper().mappingWrapperConstructor( + fieldInfo.isFieldIsMap(), SqlKeyword.IN, fieldInfo.getJoinColumn(), itemList, fieldInfo); + list.forEach(i -> { + List data = joinList.stream().filter(j -> fieldInfo.joinFieldGet(j) + .equals(fieldInfo.thisFieldGet(i))).collect(Collectors.toList()); + MPJTableFieldInfo.bind(fieldInfo, i, data); + }); + } else { + list.forEach(i -> fieldInfo.fieldSet(i, new ArrayList<>())); + } } } } diff --git a/src/main/java/com/github/yulichang/base/service/MPJDeepService.java b/src/main/java/com/github/yulichang/base/service/MPJDeepService.java index fb60767..a2fe8c1 100644 --- a/src/main/java/com/github/yulichang/base/service/MPJDeepService.java +++ b/src/main/java/com/github/yulichang/base/service/MPJDeepService.java @@ -8,15 +8,14 @@ import com.baomidou.mybatisplus.core.metadata.MPJTableInfo; import com.baomidou.mybatisplus.core.metadata.MPJTableInfoHelper; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; import com.baomidou.mybatisplus.extension.service.IService; import com.github.yulichang.annotation.MPJMapping; import com.github.yulichang.base.MPJBaseMapper; +import com.github.yulichang.toolkit.LambdaUtils; import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; /** @@ -30,7 +29,7 @@ import java.util.stream.Collectors; * @see MPJMapping * @since 1.2.0 */ -@SuppressWarnings("unused") +@SuppressWarnings({"unused", "unchecked"}) public interface MPJDeepService extends IService { Class currentModelClass(); @@ -40,10 +39,34 @@ public interface MPJDeepService extends IService { * * @param id 主键ID列表 */ - default T getByIdDeep(Serializable id) { + default T getByIdDeep(Serializable id) { return ((MPJBaseMapper) getBaseMapper()).selectByIdDeep(id); } + /** + * 根据 ID 深度查询 + *

+ * JDK 默认不推荐泛型数组,会引起 Java堆污染(Heap Pollution) + * + * @param id 主键ID列表 + * @param property 需要关联的字段 + */ + default T getByIdDeep(Serializable id, SFunction... property) { + return ((MPJBaseMapper) getBaseMapper()).selectByIdDeep(id, property); + } + + /** + * 针对可变参数堆污染提供的重载 + * list为null或空,会查询全部映射关系 + *

+ * 例: getByIdDeep(id, Arrays.asList(User::getId, ... )) + * + * @param id 主键ID列表 + * @param property 需要关联的字段 + */ + default T getByIdDeep(Serializable id, List> property) { + return ((MPJBaseMapper) getBaseMapper()).selectByIdDeep(id, property); + } /** * 查询(根据ID 批量查询) @@ -54,6 +77,31 @@ public interface MPJDeepService extends IService { return ((MPJBaseMapper) getBaseMapper()).selectBatchIdsDeep(idList); } + /** + * 查询(根据ID 批量查询) + *

+ * JDK 默认不推荐泛型数组,会引起 Java堆污染(Heap Pollution) + * + * @param idList 主键ID列表 + * @param property 需要关联的字段 + */ + default List listByIdsDeep(Collection idList, SFunction... property) { + return ((MPJBaseMapper) getBaseMapper()).selectBatchIdsDeep(idList, Arrays.asList(property)); + } + + /** + * 查询(根据ID 批量查询) + * list为null或空,会查询全部映射关系 + *

+ * 例: listByIdsDeep(idList, Arrays.asList(User::getId, ... )) + * + * @param idList 主键ID列表 + * @param property 需要关联的字段 + */ + default List listByIdsDeep(Collection idList, List> property) { + return ((MPJBaseMapper) getBaseMapper()).selectBatchIdsDeep(idList, property); + } + /** * 查询(根据 columnMap 条件) * @@ -63,6 +111,31 @@ public interface MPJDeepService extends IService { return ((MPJBaseMapper) getBaseMapper()).selectByMapDeep(columnMap); } + /** + * 查询(根据 columnMap 条件) + *

+ * JDK 默认不推荐泛型数组,会引起 Java堆污染(Heap Pollution) + * + * @param columnMap 表字段 map 对象 + * @param property 需要关联的字段 + */ + default List listByMapDeep(Map columnMap, SFunction... property) { + return ((MPJBaseMapper) getBaseMapper()).selectByMapDeep(columnMap, Arrays.asList(property)); + } + + /** + * 查询(根据 columnMap 条件) + * list为null或空,会查询全部映射关系 + *

+ * 例: listByMapDeep(columnMap, Arrays.asList(User::getId, ... )) + * + * @param columnMap 表字段 map 对象 + * @param property 需要关联的字段 + */ + default List listByMapDeep(Map columnMap, List> property) { + return ((MPJBaseMapper) getBaseMapper()).selectByMapDeep(columnMap, property); + } + /** * 根据 Wrapper,查询一条记录
@@ -74,6 +147,32 @@ public interface MPJDeepService extends IService { return ((MPJBaseMapper) getBaseMapper()).selectOneDeep(queryWrapper); } + /** + * 根据 Wrapper,查询一条记录
+ *

结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1")

+ *

+ * JDK 默认不推荐泛型数组,会引起 Java堆污染(Heap Pollution) + * + * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper} + * @param property 需要关联的字段 + */ + default T getOneDeep(Wrapper queryWrapper, SFunction... property) { + return ((MPJBaseMapper) getBaseMapper()).selectOneDeep(queryWrapper, Arrays.asList(property)); + } + + /** + * 根据 Wrapper,查询一条记录
+ * list为null或空,会查询全部映射关系
+ *

结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1")

+ *

+ * 例: getOneDeep(queryWrapper, Arrays.asList(User::getId, ... )) + * + * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper} + * @param property 需要关联的字段 + */ + default T getOneDeep(Wrapper queryWrapper, List> property) { + return ((MPJBaseMapper) getBaseMapper()).selectOneDeep(queryWrapper, property); + } /** * 根据 Wrapper,查询一条记录 @@ -82,7 +181,34 @@ public interface MPJDeepService extends IService { * @param throwEx 有多个 result 是否抛出异常 */ default T getOneDeep(Wrapper queryWrapper, boolean throwEx) { - return ((MPJBaseMapper) getBaseMapper()).queryMapping(getOne(queryWrapper, throwEx)); + return ((MPJBaseMapper) getBaseMapper()).queryMapping(getOne(queryWrapper, throwEx), null); + } + + /** + * 根据 Wrapper,查询一条记录 + *

+ * JDK 默认不推荐泛型数组,会引起 Java堆污染(Heap Pollution) + * + * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper} + * @param throwEx 有多个 result 是否抛出异常 + * @param property 需要关联的字段 + */ + default T getOneDeep(Wrapper queryWrapper, boolean throwEx, SFunction... property) { + return ((MPJBaseMapper) getBaseMapper()).queryMapping(getOne(queryWrapper, throwEx), Arrays.asList(property)); + } + + /** + * 根据 Wrapper,查询一条记录 + * list为null或空,会查询全部映射关系 + *

+ * 例: getOneDeep(queryWrapper, throwEx, Arrays.asList(User::getId, ... )) + * + * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper} + * @param throwEx 有多个 result 是否抛出异常 + * @param property 需要关联的字段 + */ + default T getOneDeep(Wrapper queryWrapper, boolean throwEx, List> property) { + return ((MPJBaseMapper) getBaseMapper()).queryMapping(getOne(queryWrapper, throwEx), property); } /** @@ -91,23 +217,33 @@ public interface MPJDeepService extends IService { * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper} */ default Map getMapDeep(Wrapper queryWrapper) { - Map map = getMap(queryWrapper); - if (CollectionUtils.isNotEmpty(map)) { - MPJTableInfo tableInfo = MPJTableInfoHelper.getTableInfo(currentModelClass()); - if (tableInfo.isHasMapping()) { - for (MPJTableFieldInfo fieldInfo : tableInfo.getFieldList()) { - Object o = map.get(fieldInfo.getThisMapKey()); - if (o != null) { - List data = (List) fieldInfo.getJoinMapper().mappingWrapperConstructor(fieldInfo.isFieldIsMap(), - SqlKeyword.EQ, fieldInfo.getJoinColumn(), o, fieldInfo); - MPJTableFieldInfo.bindMap(fieldInfo, map, data); - } - } - } - } - return map; + return queryMapMapping(getMap(queryWrapper), null); } + /** + * 根据 Wrapper,查询一条记录 + *

+ * JDK 默认不推荐泛型数组,会引起 Java堆污染(Heap Pollution) + * + * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper} + * @param property 需要关联的字段 + */ + default Map getMapDeep(Wrapper queryWrapper, SFunction... property) { + return queryMapMapping(getMap(queryWrapper), Arrays.asList(property)); + } + + /** + * 根据 Wrapper,查询一条记录 + * list为null或空,会查询全部映射关系 + *

+ * 例:getMapDeep(queryWrapper, Arrays.asList(User::getId, ... )) + * + * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper} + * @param property 需要关联的字段 + */ + default Map getMapDeep(Wrapper queryWrapper, List> property) { + return queryMapMapping(getMap(queryWrapper), property); + } /** * 查询列表 @@ -118,6 +254,31 @@ public interface MPJDeepService extends IService { return ((MPJBaseMapper) getBaseMapper()).selectListDeep(queryWrapper); } + /** + * 查询列表 + *

+ * JDK 默认不推荐泛型数组,会引起 Java堆污染(Heap Pollution) + * + * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper} + * @param property 需要关联的字段 + */ + default List listDeep(Wrapper queryWrapper, SFunction... property) { + return ((MPJBaseMapper) getBaseMapper()).selectListDeep(queryWrapper, Arrays.asList(property)); + } + + /** + * 查询列表 + * list为null或空,会查询全部映射关系 + *

+ * 例:listDeep(queryWrapper, Arrays.asList(User::getId, ... )) + * + * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper} + * @param property 需要关联的字段 + */ + default List listDeep(Wrapper queryWrapper, List> property) { + return ((MPJBaseMapper) getBaseMapper()).selectListDeep(queryWrapper, property); + } + /** * 查询所有 * @@ -127,6 +288,31 @@ public interface MPJDeepService extends IService { return ((MPJBaseMapper) getBaseMapper()).selectListDeep(Wrappers.emptyWrapper()); } + /** + * 查询所有 + *

+ * JDK 默认不推荐泛型数组,会引起 Java堆污染(Heap Pollution) + * + * @param property 需要关联的字段 + * @see Wrappers#emptyWrapper() + */ + default List listDeep(SFunction... property) { + return ((MPJBaseMapper) getBaseMapper()).selectListDeep(Wrappers.emptyWrapper(), Arrays.asList(property)); + } + + /** + * 查询所有 + * list为null或空,会查询全部映射关系 + *

+ * 例:listDeep(Arrays.asList(User::getId, ... )) + * + * @param property 需要关联的字段 + * @see Wrappers#emptyWrapper() + */ + default List listDeep(List> property) { + return ((MPJBaseMapper) getBaseMapper()).selectListDeep(Wrappers.emptyWrapper(), property); + } + /** * 翻页查询 * @@ -135,7 +321,38 @@ public interface MPJDeepService extends IService { */ default > E pageDeep(E page, Wrapper queryWrapper) { E e = page(page, queryWrapper); - ((MPJBaseMapper) getBaseMapper()).queryMapping(e.getRecords()); + ((MPJBaseMapper) getBaseMapper()).queryMapping(e.getRecords(), null); + return e; + } + + /** + * 翻页查询 + *

+ * JDK 默认不推荐泛型数组,会引起 Java堆污染(Heap Pollution) + * + * @param page 翻页对象 + * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper} + * @param property 需要关联的字段 + */ + default > E pageDeep(E page, Wrapper queryWrapper, SFunction... property) { + E e = page(page, queryWrapper); + ((MPJBaseMapper) getBaseMapper()).queryMapping(e.getRecords(), Arrays.asList(property)); + return e; + } + + /** + * 翻页查询 + * list为null或空,会查询全部映射关系 + *

+ * 例:pageDeep(page, queryWrapper, Arrays.asList(User::getId, ... )) + * + * @param page 翻页对象 + * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper} + * @param property 需要关联的字段 + */ + default > E pageDeep(E page, Wrapper queryWrapper, List> property) { + E e = page(page, queryWrapper); + ((MPJBaseMapper) getBaseMapper()).queryMapping(e.getRecords(), property); return e; } @@ -147,7 +364,38 @@ public interface MPJDeepService extends IService { */ default > E pageDeep(E page) { E e = page(page); - ((MPJBaseMapper) getBaseMapper()).queryMapping(e.getRecords()); + ((MPJBaseMapper) getBaseMapper()).queryMapping(e.getRecords(), null); + return e; + } + + /** + * 无条件翻页查询 + *

+ * JDK 默认不推荐泛型数组,会引起 Java堆污染(Heap Pollution) + * + * @param page 翻页对象 + * @param property 需要关联的字段 + * @see Wrappers#emptyWrapper() + */ + default > E pageDeep(E page, SFunction... property) { + E e = page(page); + ((MPJBaseMapper) getBaseMapper()).queryMapping(e.getRecords(), Arrays.asList(property)); + return e; + } + + /** + * 无条件翻页查询 + * list为null或空,会查询全部映射关系 + *

+ * 例:pageDeep(page, Arrays.asList(User::getId, ... )) + * + * @param page 翻页对象 + * @param property 需要关联的字段 + * @see Wrappers#emptyWrapper() + */ + default > E pageDeep(E page, List> property) { + E e = page(page); + ((MPJBaseMapper) getBaseMapper()).queryMapping(e.getRecords(), property); return e; } @@ -157,7 +405,32 @@ public interface MPJDeepService extends IService { * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper} */ default List> listMapsDeep(Wrapper queryWrapper) { - return queryMapMapping(listMaps(queryWrapper)); + return queryMapMapping(listMaps(queryWrapper), null); + } + + /** + * 查询列表 + *

+ * JDK 默认不推荐泛型数组,会引起 Java堆污染(Heap Pollution) + * + * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper} + * @param property 需要关联的字段 + */ + default List> listMapsDeep(Wrapper queryWrapper, SFunction... property) { + return queryMapMapping(listMaps(queryWrapper), Arrays.asList(property)); + } + + /** + * 查询列表 + * list为null或空,会查询全部映射关系 + *

+ * 例:listMapsDeep(queryWrapper, Arrays.asList(User::getId, ... )) + * + * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper} + * @param property 需要关联的字段 + */ + default List> listMapsDeep(Wrapper queryWrapper, List> property) { + return queryMapMapping(listMaps(queryWrapper), property); } /** @@ -166,9 +439,33 @@ public interface MPJDeepService extends IService { * @see Wrappers#emptyWrapper() */ default List> listMapsDeep() { - return queryMapMapping(listMaps()); + return queryMapMapping(listMaps(), null); } + /** + * 查询所有列表 + *

+ * JDK 默认不推荐泛型数组,会引起 Java堆污染(Heap Pollution) + * + * @param property 需要关联的字段 + * @see Wrappers#emptyWrapper() + */ + default List> listMapsDeep(SFunction... property) { + return queryMapMapping(listMaps(), Arrays.asList(property)); + } + + /** + * 查询所有列表 + * list为null或空,会查询全部映射关系 + *

+ * 例:listMapsDeep(Arrays.asList(User::getId, ... )) + * + * @param property 需要关联的字段 + * @see Wrappers#emptyWrapper() + */ + default List> listMapsDeep(List> property) { + return queryMapMapping(listMaps(), property); + } /** * 翻页查询 @@ -178,7 +475,38 @@ public interface MPJDeepService extends IService { */ default >> E pageMapsDeep(E page, Wrapper queryWrapper) { E e = pageMaps(page, queryWrapper); - queryMapMapping(e.getRecords()); + queryMapMapping(e.getRecords(), null); + return e; + } + + /** + * 翻页查询 + *

+ * JDK 默认不推荐泛型数组,会引起 Java堆污染(Heap Pollution) + * + * @param page 翻页对象 + * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper} + * @param property 需要关联的字段 + */ + default >> E pageMapsDeep(E page, Wrapper queryWrapper, SFunction... property) { + E e = pageMaps(page, queryWrapper); + queryMapMapping(e.getRecords(), Arrays.asList(property)); + return e; + } + + /** + * 翻页查询 + * list为null或空,会查询全部映射关系 + *

+ * 例:pageMapsDeep(page, queryWrapper, Arrays.asList(User::getId, ... )) + * + * @param page 翻页对象 + * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper} + * @param property 需要关联的字段 + */ + default >> E pageMapsDeep(E page, Wrapper queryWrapper, List> property) { + E e = pageMaps(page, queryWrapper); + queryMapMapping(e.getRecords(), property); return e; } @@ -190,55 +518,121 @@ public interface MPJDeepService extends IService { */ default >> E pageMapsDeep(E page) { E e = pageMaps(page); - queryMapMapping(e.getRecords()); + queryMapMapping(e.getRecords(), null); return e; } + /** + * 无条件翻页查询 + *

+ * JDK 默认不推荐泛型数组,会引起 Java堆污染(Heap Pollution) + * + * @param page 翻页对象 + * @param property 需要关联的字段 + * @see Wrappers#emptyWrapper() + */ + default >> E pageMapsDeep(E page, SFunction... property) { + E e = pageMaps(page); + queryMapMapping(e.getRecords(), Arrays.asList(property)); + return e; + } /** - * 查询映射关系 - * 对结果进行二次查询 - * 可以自行查询然后在通过此方法进行二次查询 + * 无条件翻页查询 + * list为null或空,会查询全部映射关系 + *

+ * 例:pageMapsDeep(page, Arrays.asList(User::getId, ... )) + * + * @param page 翻页对象 + * @param property 需要关联的字段 + * @see Wrappers#emptyWrapper() + */ + default >> E pageMapsDeep(E page, List> property) { + E e = pageMaps(page); + queryMapMapping(e.getRecords(), property); + return e; + } + + /** + * 查询映射关系
+ * 对结果进行二次查询
+ * 可以自行查询然后在通过此方法进行二次查询
+ * list为null或空,会查询全部映射关系
+ * + * @param map 第一次查询结果 + */ + default Map queryMapMapping(Map map, List> property) { + if (CollectionUtils.isNotEmpty(map)) { + MPJTableInfo tableInfo = MPJTableInfoHelper.getTableInfo(currentModelClass()); + if (tableInfo.isHasMapping()) { + boolean hasProperty = CollectionUtils.isNotEmpty(property); + List list = hasProperty ? property.stream().map(LambdaUtils::getName).collect( + Collectors.toList()) : null; + for (MPJTableFieldInfo fieldInfo : tableInfo.getFieldList()) { + if (!hasProperty || list.contains(fieldInfo.getProperty())) { + Object o = map.get(fieldInfo.getThisMapKey()); + if (o != null) { + List data = (List) fieldInfo.getJoinMapper().mappingWrapperConstructor( + fieldInfo.isFieldIsMap(), SqlKeyword.EQ, fieldInfo.getJoinColumn(), o, fieldInfo); + MPJTableFieldInfo.bindMap(fieldInfo, map, data); + } + } + } + } + } + return map; + } + + /** + * 查询映射关系
+ * 对结果进行二次查询
+ * 可以自行查询然后在通过此方法进行二次查询
+ * list为null或空,会查询全部映射关系
* * @param list 第一次查询结果 */ @SuppressWarnings("unchecked") - default List> queryMapMapping(List> list) { + default List> queryMapMapping(List> list, List> property) { if (CollectionUtils.isEmpty(list)) { return list; } MPJTableInfo tableInfo = MPJTableInfoHelper.getTableInfo(currentModelClass()); if (tableInfo.isHasMapping()) { + boolean hasProperty = CollectionUtils.isNotEmpty(property); + List listProperty = hasProperty ? property.stream().map(LambdaUtils::getName).collect( + Collectors.toList()) : null; for (MPJTableFieldInfo fieldInfo : tableInfo.getFieldList()) { - List itemList = list.stream().map(m -> m.get(fieldInfo.getThisMapKey())).collect(Collectors.toList()); - if (CollectionUtils.isNotEmpty(itemList)) { - if (fieldInfo.isFieldIsMap()) { - List> joinList = (List>) fieldInfo.getJoinMapper() - .mappingWrapperConstructor(fieldInfo.isFieldIsMap(), SqlKeyword.IN, - fieldInfo.getJoinColumn(), itemList, fieldInfo); - list.forEach(i -> { - List> data = joinList.stream().filter(j -> j.containsKey(fieldInfo.getJoinMapKey()) - && j.get(fieldInfo.getJoinMapKey()).equals(i.get(fieldInfo.getThisMapKey()))).collect(Collectors.toList()); - MPJTableFieldInfo.bindMap(fieldInfo, i, data); - }); + if (!hasProperty || listProperty.contains(fieldInfo.getProperty())) { + List itemList = list.stream().map(m -> m.get(fieldInfo.getThisMapKey())) + .collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(itemList)) { + if (fieldInfo.isFieldIsMap()) { + List> joinList = (List>) fieldInfo.getJoinMapper() + .mappingWrapperConstructor(fieldInfo.isFieldIsMap(), SqlKeyword.IN, + fieldInfo.getJoinColumn(), itemList, fieldInfo); + list.forEach(i -> { + List> data = joinList.stream().filter(j -> j.containsKey( + fieldInfo.getJoinMapKey()) && j.get(fieldInfo.getJoinMapKey()).equals( + i.get(fieldInfo.getThisMapKey()))).collect(Collectors.toList()); + MPJTableFieldInfo.bindMap(fieldInfo, i, data); + }); + } else { + List joinList = (List) fieldInfo.getJoinMapper().mappingWrapperConstructor( + fieldInfo.isFieldIsMap(), SqlKeyword.IN, fieldInfo.getJoinColumn(), itemList, fieldInfo); + list.forEach(i -> { + List data = joinList.stream().filter(j -> { + Object o = fieldInfo.joinFieldGet(j); + return o != null && o.equals(i.get(fieldInfo.getThisMapKey())); + }).collect(Collectors.toList()); + MPJTableFieldInfo.bindMap(fieldInfo, i, data); + }); + } } else { - List joinList = (List) fieldInfo.getJoinMapper().mappingWrapperConstructor( - fieldInfo.isFieldIsMap(), SqlKeyword.IN, fieldInfo.getJoinColumn(), itemList, fieldInfo); - list.forEach(i -> { - List data = joinList.stream().filter(j -> { - Object o = fieldInfo.joinFieldGet(j); - return o != null && o.equals(i.get(fieldInfo.getThisMapKey())); - }).collect(Collectors.toList()); - MPJTableFieldInfo.bindMap(fieldInfo, i, data); - }); + list.forEach(i -> i.put(fieldInfo.getField().getName(), new ArrayList<>())); } - } else { - list.forEach(i -> i.put(fieldInfo.getField().getName(), new ArrayList<>())); } } } return list; } - - } diff --git a/src/main/java/com/github/yulichang/injector/MPJSqlInjector.java b/src/main/java/com/github/yulichang/injector/MPJSqlInjector.java index 6baeb1e..12b5d76 100644 --- a/src/main/java/com/github/yulichang/injector/MPJSqlInjector.java +++ b/src/main/java/com/github/yulichang/injector/MPJSqlInjector.java @@ -2,9 +2,11 @@ package com.github.yulichang.injector; import com.baomidou.mybatisplus.core.injector.AbstractMethod; import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector; +import com.baomidou.mybatisplus.core.mapper.Mapper; import com.baomidou.mybatisplus.core.metadata.MPJTableInfoHelper; 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.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils; import com.github.yulichang.method.*; @@ -12,6 +14,7 @@ import org.apache.ibatis.builder.MapperBuilderAssistant; import org.apache.ibatis.logging.Log; import org.apache.ibatis.logging.LogFactory; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.core.GenericTypeResolver; import java.util.List; import java.util.Set; @@ -42,7 +45,7 @@ public class MPJSqlInjector extends DefaultSqlInjector { @Override public void inspectInject(MapperBuilderAssistant builderAssistant, Class mapperClass) { - Class modelClass = extractModelClass(mapperClass); + Class modelClass = getSuperClassGenericType(mapperClass, Mapper.class, 0); if (modelClass != null) { String className = mapperClass.toString(); Set mapperRegistryCache = GlobalConfigUtils.getMapperRegistryCache(builderAssistant.getConfiguration()); @@ -50,14 +53,19 @@ public class MPJSqlInjector extends DefaultSqlInjector { List methodList = this.getMethodList(mapperClass); if (CollectionUtils.isNotEmpty(methodList)) { TableInfo tableInfo = TableInfoHelper.initTableInfo(builderAssistant, modelClass); - MPJTableInfoHelper.initTableInfo(builderAssistant, extractModelClass(mapperClass), mapperClass); + MPJTableInfoHelper.initTableInfo(builderAssistant, modelClass, mapperClass); // 循环注入自定义方法 methodList.forEach(m -> m.inject(builderAssistant, mapperClass, modelClass, tableInfo)); } else { - logger.debug(mapperClass + ", No effective injection method was found."); + logger.debug(mapperClass.toString() + ", No effective injection method was found."); } mapperRegistryCache.add(className); } } } + + public static Class getSuperClassGenericType(final Class clazz, final Class genericIfc, final int index) { + Class[] typeArguments = GenericTypeResolver.resolveTypeArguments(ClassUtils.getUserClass(clazz), genericIfc); + return null == typeArguments ? null : typeArguments[index]; + } }