From a6c577ee889ef1180dc19b9f8db49eb24553fce6 Mon Sep 17 00:00:00 2001 From: bjdys Date: Thu, 12 Aug 2021 11:56:02 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=80=E5=AF=B9=E4=B8=80=20=E4=B8=80?= =?UTF-8?q?=E5=AF=B9=E5=A4=9A=20=E5=85=B3=E7=B3=BB=E6=98=A0=E5=B0=84?= =?UTF-8?q?=E6=B3=A8=E8=A7=A3=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/metadata/MPJMappingWrapper.java | 18 ++--- .../core/metadata/MPJTableFieldInfo.java | 77 ++++++++++++++++--- .../yulichang/annotation/MPJMapping.java | 22 ++++-- .../yulichang/annotation/MPJMappingApply.java | 2 +- .../yulichang/base/MPJBaseDeepService.java | 46 +++++------ .../github/yulichang/base/MPJBaseMapper.java | 8 +- 6 files changed, 117 insertions(+), 56 deletions(-) diff --git a/src/main/java/com/baomidou/mybatisplus/core/metadata/MPJMappingWrapper.java b/src/main/java/com/baomidou/mybatisplus/core/metadata/MPJMappingWrapper.java index 7a1bb20..24141b0 100644 --- a/src/main/java/com/baomidou/mybatisplus/core/metadata/MPJMappingWrapper.java +++ b/src/main/java/com/baomidou/mybatisplus/core/metadata/MPJMappingWrapper.java @@ -7,7 +7,7 @@ import com.github.yulichang.annotation.MPJMapping; import com.github.yulichang.annotation.MPJMappingApply; import com.github.yulichang.annotation.MPJMappingCondition; import lombok.AllArgsConstructor; -import lombok.Data; +import lombok.Getter; import java.util.ArrayList; import java.util.List; @@ -18,7 +18,7 @@ import java.util.List; * @author yulichang * @since 1.2.0 */ -@Data +@Getter public class MPJMappingWrapper { private final boolean hasFirst; @@ -69,18 +69,18 @@ public class MPJMappingWrapper { } } - @Data + @Getter @AllArgsConstructor public static class Apply { - private String sql; - private String[] val; + private final String sql; + private final String[] val; } - @Data + @Getter @AllArgsConstructor public static class Condition { - private SqlKeyword keyword; - private String column; - private String[] val; + private final SqlKeyword keyword; + private final String column; + private final String[] val; } } 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 42e3db6..5b23ed1 100644 --- a/src/main/java/com/baomidou/mybatisplus/core/metadata/MPJTableFieldInfo.java +++ b/src/main/java/com/baomidou/mybatisplus/core/metadata/MPJTableFieldInfo.java @@ -13,9 +13,12 @@ import lombok.Getter; 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; /** * 字段属性 @@ -36,15 +39,15 @@ public class MPJTableFieldInfo { /** * 属性 */ - private final Field field; + private Field field; /** - * 属性 + * 数据结构是否是Map或者List */ - private final boolean fieldIsMap; + private boolean fieldIsMap; /** * 属性是否是集合 */ - private final boolean isCollection; + private boolean isCollection; /** * 当前映射属性 */ @@ -91,22 +94,24 @@ public class MPJTableFieldInfo { * 关联查询条件配置 */ private final MPJMappingWrapper wrapper; + /** + * 一对一查询结果数量不匹配是是否抛出异常 + */ + private final boolean isThrowExp; /** * 初始化关联字段信息 */ - public MPJTableFieldInfo(Class entityType, MPJMapping mapping, Field field) { - field.setAccessible(true); + public MPJTableFieldInfo(Class entityType, MPJMapping mapping, Field field1) { + initField(field1); this.entityType = entityType; - this.field = field; this.joinClass = mapping.tag(); - this.isCollection = Collection.class.isAssignableFrom(field.getType()); + this.isThrowExp = mapping.isThrowExp(); this.thisMapKey = StringUtils.isBlank(mapping.thisMapKey()) ? null : mapping.thisMapKey(); this.joinMapKey = StringUtils.isBlank(mapping.joinMapKsy()) ? null : mapping.joinMapKsy(); - this.fieldIsMap = mapping.isMap();//TODO 应该可以自动检测 this.wrapper = new MPJMappingWrapper(mapping); - if (this.isCollection && field.getType() != List.class && field.getType() != ArrayList.class) { - throw new MPJException("对多关系的数据结构目前只支持 暂不支持其他Collection实现 " + field.getType().getTypeName()); + if (this.isCollection && this.field.getType() != List.class && this.field.getType() != ArrayList.class) { + throw new MPJException("对多关系的数据结构目前只支持 暂不支持其他Collection实现 " + this.field.getType().getTypeName()); } if (StringUtils.isNotBlank(mapping.joinField())) { this.joinProperty = mapping.joinField(); @@ -124,6 +129,28 @@ public class MPJTableFieldInfo { } } + private void initField(Field field) { + field.setAccessible(true); + this.field = field; + this.isCollection = Collection.class.isAssignableFrom(field.getType()); + + if (Map.class.isAssignableFrom(field.getType())) { + this.fieldIsMap = true; + } else { + if (field.getGenericType() instanceof ParameterizedType) { + ParameterizedType t = (ParameterizedType) field.getGenericType(); + Type type = t.getActualTypeArguments()[0]; + if (type instanceof ParameterizedType) { + this.fieldIsMap = ((ParameterizedType) type).getRawType() == Map.class; + } else { + this.fieldIsMap = false; + } + } else { + this.fieldIsMap = false; + } + } + } + @SuppressWarnings("ConstantConditions") public Field getThisField() { if (this.thisField == null) { @@ -240,4 +267,32 @@ public class MPJTableFieldInfo { this.joinField.getName() + " , " + o.getClass().getName()); } } + + public static void bind(MPJTableFieldInfo fieldInfo, T i, List data) { + if (!fieldInfo.isCollection()) { + 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 (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 f1f60fd..264ff15 100644 --- a/src/main/java/com/github/yulichang/annotation/MPJMapping.java +++ b/src/main/java/com/github/yulichang/annotation/MPJMapping.java @@ -19,13 +19,6 @@ public @interface MPJMapping { */ Class tag(); - /** - * 当前类的属性数据结构 是否是Map 或 List - * 如果是 true 关联查询会调用 getMap() / listMaps() 等Map相关方法进行匹配 - * 如果是 false 关联查询会调用 getOne() / getById() / list() 等实体类相关方法进行匹配 - */ - boolean isMap() default false; - /** * 当前类的关联的字段名称 (是实体类字段名称而不是数据库字段名称) * 默认获取当前类上定义的主键 @TableId @@ -38,6 +31,20 @@ public @interface MPJMapping { */ String joinField() default ""; + /** + * 当前类的属性数据结构 是否是Map 或 List + * 如果是 true 关联查询会调用 getMap() / listMaps() 等Map相关方法进行匹配 + * 如果是 false 关联查询会调用 getOne() / getById() / list() 等实体类相关方法进行匹配 + */ + boolean isMap() default false; + + /** + * 一对一查询时 如果查询到多条记录是否抛出异常 + * true 抛出异常 + * false 不抛异常,获取列表第一条数据 + */ + boolean isThrowExp() default true; + /** * 针对查询结果map的时候使用 * 默认为thisField对应的数据库列名 @@ -82,6 +89,7 @@ public @interface MPJMapping { /** * 映射表查询条件之 last + * 建议不要在这使用分页语句,会导致关联查的时候查询不全 * 等效于 Wrappers.query().last(xxx); */ String last() default ""; diff --git a/src/main/java/com/github/yulichang/annotation/MPJMappingApply.java b/src/main/java/com/github/yulichang/annotation/MPJMappingApply.java index a060ad2..8784957 100644 --- a/src/main/java/com/github/yulichang/annotation/MPJMappingApply.java +++ b/src/main/java/com/github/yulichang/annotation/MPJMappingApply.java @@ -17,5 +17,5 @@ public @interface MPJMappingApply { /** * .apply() 对应的可变参数 */ - String[] args(); + String[] args() default {}; } diff --git a/src/main/java/com/github/yulichang/base/MPJBaseDeepService.java b/src/main/java/com/github/yulichang/base/MPJBaseDeepService.java index 7ed7143..a984e3f 100644 --- a/src/main/java/com/github/yulichang/base/MPJBaseDeepService.java +++ b/src/main/java/com/github/yulichang/base/MPJBaseDeepService.java @@ -17,7 +17,6 @@ import java.util.Collection; import java.util.List; import java.util.Map; import java.util.stream.Collectors; -import java.util.stream.Stream; /** * 深度查询 @@ -98,9 +97,9 @@ public interface MPJBaseDeepService extends IService { for (MPJTableFieldInfo fieldInfo : tableInfo.getFieldList()) { Object o = map.get(fieldInfo.getThisMapKey()); if (o != null) { - map.put(fieldInfo.getField().getName(), fieldInfo.getJoinMapper() - .mappingWrapperConstructor(fieldInfo.isCollection(), fieldInfo.isFieldIsMap(), SqlKeyword.EQ, - fieldInfo.getJoinColumn(), o, fieldInfo)); + List data = (List) fieldInfo.getJoinMapper().mappingWrapperConstructor(fieldInfo.isFieldIsMap(), + SqlKeyword.EQ, fieldInfo.getJoinColumn(), o, fieldInfo); + MPJTableFieldInfo.bindMap(fieldInfo, map, data); } } } @@ -218,9 +217,9 @@ public interface MPJBaseDeepService extends IService { for (MPJTableFieldInfo fieldInfo : tableInfo.getFieldList()) { Object get = fieldInfo.thisFieldGet(t); if (get != null) { - fieldInfo.fieldSet(t, fieldInfo.getJoinMapper().mappingWrapperConstructor(fieldInfo.isCollection(), - fieldInfo.isFieldIsMap(), SqlKeyword.EQ, fieldInfo.getJoinColumn(), - get, fieldInfo)); + List o = (List) fieldInfo.getJoinMapper().mappingWrapperConstructor(fieldInfo.isFieldIsMap(), + SqlKeyword.EQ, fieldInfo.getJoinColumn(), get, fieldInfo); + MPJTableFieldInfo.bind(fieldInfo, t, o); } } } @@ -243,13 +242,12 @@ public interface MPJBaseDeepService extends IService { 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(true, + List joinList = (List) fieldInfo.getJoinMapper().mappingWrapperConstructor( fieldInfo.isFieldIsMap(), SqlKeyword.IN, fieldInfo.getJoinColumn(), itemList, fieldInfo); list.forEach(i -> { - Stream stream = joinList.stream().filter(j -> - fieldInfo.joinFieldGet(j).equals(fieldInfo.thisFieldGet(i))); - fieldInfo.fieldSet(i, fieldInfo.isCollection() ? stream.collect(Collectors.toList()) : - stream.findFirst().orElse(null)); + 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<>())); @@ -259,6 +257,7 @@ public interface MPJBaseDeepService extends IService { return list; } + /** * 查询映射关系 * 对结果进行二次查询 @@ -277,24 +276,23 @@ public interface MPJBaseDeepService extends IService { 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(true, - fieldInfo.isFieldIsMap(), SqlKeyword.IN, fieldInfo.getJoinColumn(), itemList, fieldInfo); + List> joinList = (List>) fieldInfo.getJoinMapper() + .mappingWrapperConstructor(fieldInfo.isFieldIsMap(), SqlKeyword.IN, + fieldInfo.getJoinColumn(), itemList, fieldInfo); list.forEach(i -> { - Stream> stream = joinList.stream().filter(j -> j.containsKey(fieldInfo.getJoinMapKey()) - && j.get(fieldInfo.getJoinMapKey()).equals(i.get(fieldInfo.getThisMapKey()))); - i.put(fieldInfo.getField().getName(), fieldInfo.isCollection() ? stream.collect(Collectors.toList()) : - stream.findFirst().orElse(null)); + 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(true, + List joinList = (List) fieldInfo.getJoinMapper().mappingWrapperConstructor( fieldInfo.isFieldIsMap(), SqlKeyword.IN, fieldInfo.getJoinColumn(), itemList, fieldInfo); list.forEach(i -> { - Stream stream = joinList.stream().filter(j -> { + List data = joinList.stream().filter(j -> { Object o = fieldInfo.joinFieldGet(j); return o != null && o.equals(i.get(fieldInfo.getThisMapKey())); - }); - i.put(fieldInfo.getField().getName(), fieldInfo.isCollection() ? stream.collect(Collectors.toList()) : - stream.findFirst().orElse(null)); + }).collect(Collectors.toList()); + MPJTableFieldInfo.bindMap(fieldInfo, i, data); }); } } else { @@ -304,4 +302,6 @@ public interface MPJBaseDeepService extends IService { } return list; } + + } diff --git a/src/main/java/com/github/yulichang/base/MPJBaseMapper.java b/src/main/java/com/github/yulichang/base/MPJBaseMapper.java index 0e435eb..7ee7bcc 100644 --- a/src/main/java/com/github/yulichang/base/MPJBaseMapper.java +++ b/src/main/java/com/github/yulichang/base/MPJBaseMapper.java @@ -83,7 +83,7 @@ public interface MPJBaseMapper extends BaseMapper { * 映射 wrapper 构造器 * 仅对使用 @MPJMapping 时使用 */ - default Object mappingWrapperConstructor(boolean isCollection, boolean selectMap, SqlKeyword keyword, + default Object mappingWrapperConstructor(boolean selectMap, SqlKeyword keyword, String column, Object val, MPJTableFieldInfo fieldInfo) { MPJMappingWrapper infoWrapper = fieldInfo.getWrapper(); MappingQuery wrapper = new MappingQuery<>(); @@ -103,12 +103,10 @@ public interface MPJBaseMapper extends BaseMapper { if (infoWrapper.isHasApply()) { infoWrapper.getApplyList().forEach(a -> wrapper.apply(a.getSql(), (Object[]) a.getVal())); } - - if (selectMap) { - return isCollection ? selectMaps(wrapper) : selectMaps(wrapper).stream().findFirst().orElse(null); + return selectMaps(wrapper); } - return isCollection ? selectList(wrapper) : selectOne(wrapper); + return selectList(wrapper); } /**