From 8866a438adac7083003c8c306a3e75b76bf129d4 Mon Sep 17 00:00:00 2001 From: yunchao Date: Thu, 29 Aug 2024 09:29:09 +0800 Subject: [PATCH] =?UTF-8?q?*=20=E4=BF=AE=E5=A4=8DBindEntityByMid,=20select?= =?UTF-8?q?=E4=B8=AD=E9=97=B4=E7=BB=84=E4=BB=B6=E4=BD=BF=E7=94=A8=E5=88=AB?= =?UTF-8?q?=E5=90=8Das=E5=90=8E=EF=BC=8C=E6=9F=A5=E8=AF=A2=E7=BB=93?= =?UTF-8?q?=E6=9E=9C=E7=A9=BAnull=E6=8A=A5=E9=94=99bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mpe/bind/builder/ByMidResultBuilder.java | 487 +++++++++--------- 1 file changed, 243 insertions(+), 244 deletions(-) diff --git a/mybatis-plus-ext-bind/mybatis-plus-ext-bind-core/src/main/java/com/tangzc/mpe/bind/builder/ByMidResultBuilder.java b/mybatis-plus-ext-bind/mybatis-plus-ext-bind-core/src/main/java/com/tangzc/mpe/bind/builder/ByMidResultBuilder.java index 5e179844..e408221d 100644 --- a/mybatis-plus-ext-bind/mybatis-plus-ext-bind-core/src/main/java/com/tangzc/mpe/bind/builder/ByMidResultBuilder.java +++ b/mybatis-plus-ext-bind/mybatis-plus-ext-bind-core/src/main/java/com/tangzc/mpe/bind/builder/ByMidResultBuilder.java @@ -1,244 +1,243 @@ -package com.tangzc.mpe.bind.builder; - -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.tangzc.mpe.base.MapperScanner; -import com.tangzc.mpe.bind.metadata.FieldDescription; -import com.tangzc.mpe.bind.metadata.MidConditionDescription; -import com.tangzc.mpe.bind.metadata.OrderByDescription; -import lombok.AllArgsConstructor; -import org.springframework.util.StringUtils; - -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.function.Function; -import java.util.stream.Collectors; - -/** - * @author don - */ -@AllArgsConstructor(staticName = "newInstance") -public class ByMidResultBuilder { - - private final List beans; - private final FieldDescription.ConditionSign conditionSign; - private final List> fieldDescriptions; - private final FillDataCallback fillDataCallback; - - public void fillData() { - - // 中间表关联关系,仅限于一个条件,所以直接get(0) - MidConditionDescription midConditionDescription = conditionSign.getConditions().get(0); - - // > - Map> joinEntityMap = listEntitiesByCondition(midConditionDescription); - - // 循环填充每个bean - for (BEAN bean : beans) { - - String selfFieldVal = getSelfFieldValFromBean(midConditionDescription, bean); - List entities = joinEntityMap.getOrDefault(selfFieldVal, Collections.emptyList()); - - // 循环填充bean中的每个属性 - for (FieldDescription fieldAnnotation : fieldDescriptions) { - - List dataList = entities; - if (fillDataCallback != null) { - fillDataCallback.fillBefore(bean, fieldAnnotation, dataList); - dataList = fillDataCallback.changeDataList(bean, fieldAnnotation, dataList); - } - - fullDataToBeanField(bean, fieldAnnotation, dataList); - } - } - } - - /** - * 查询目标表的数据集合 - * - * @return > - */ - private Map> listEntitiesByCondition(MidConditionDescription midConditionDescription) { - - // 查询中间表符合要求的数据 - List midDataList = listMidData(midConditionDescription); - - // 对中间表数据进行分组,确定主表与从表的数据对应关系 - // > - Map> midDataListMap = midDataList.stream().collect(Collectors.groupingBy(midData -> { - try { - return midConditionDescription.getSelfMidFieldGetMethod().invoke(midData); - } catch (Exception e) { - throw new RuntimeException(e); - } - }, Collectors.mapping(midData -> { - try { - return midConditionDescription.getJoinMidFieldGetMethod().invoke(midData); - } catch (Exception e) { - throw new RuntimeException(e); - } - }, Collectors.toList()))); - - // 查询目标表数据 - Set joinMidFieldVals = midDataListMap.values().stream().flatMap(Collection::stream).collect(Collectors.toSet()); - List entities = listEntities(midConditionDescription, joinMidFieldVals); - // 对join表结果进行map映射 - Map entitiesMap = entities.stream().collect(Collectors.toMap(ent -> { - try { - return midConditionDescription.getJoinFieldGetMethod().invoke(ent); - } catch (Exception e) { - throw new RuntimeException(e); - } - }, Function.identity())); - - // 集合中间表数据与join表数据 - Map> dataMap = new HashMap<>(midDataListMap.size()); - midDataListMap.forEach((selfVal, joinValList) -> - dataMap.put(selfVal.toString(), - joinValList.stream().map(entitiesMap::get) - .filter(Objects::nonNull) - .collect(Collectors.toList()) - ) - ); - return dataMap; - } - - /** - * 查询join表的数据 - */ - private List listEntities(MidConditionDescription midConditionDescription, Set joinMidFieldVals) { - - if (joinMidFieldVals.isEmpty()) { - return Collections.emptyList(); - } - - QueryWrapper queryWrapper = new QueryWrapper<>(); - // 查询某些列值 - String[] selectColumns = fillDataCallback.selectColumns(beans, conditionSign, fieldDescriptions); - if (selectColumns != null && selectColumns.length > 0) { - queryWrapper.select(selectColumns); - } - // 添加主要条件 - queryWrapper.in(midConditionDescription.getJoinColumnName(), joinMidFieldVals); - // 自定义条件 - queryWrapper.apply(StringUtils.hasText(conditionSign.getCustomCondition()), conditionSign.getCustomCondition()); - // 排序 - for (OrderByDescription orderBy : conditionSign.getOrderBys()) { - queryWrapper.orderBy(true, orderBy.isAsc(), orderBy.getColumnName()); - } - // last sql - queryWrapper.last(conditionSign.getLast()); - - Class joinEntityClass = conditionSign.getJoinEntityClass(); - return MapperScanner.getMapperExecute(joinEntityClass, mapper -> mapper.selectList(queryWrapper)); - } - - /** - * 查询中间表的数据 - */ - private List listMidData(MidConditionDescription midConditionDescription) { - - // 获取bean集合中自身字段值的集合 - List selfFieldVals = new ArrayList<>(); - try { - for (BEAN bean : beans) { - selfFieldVals.add(midConditionDescription.getSelfFieldGetMethod().invoke(bean)); - } - } catch (Exception e) { - throw new RuntimeException(e); - } - - if (selfFieldVals.isEmpty()) { - return Collections.emptyList(); - } - - // 构建查询器 - QueryWrapper queryWrapper = new QueryWrapper<>(); - // 仅仅查询关联关系的两列(对于性能提升只在中间表列数很多的情况下有意义) - String joinMidColumnName = midConditionDescription.getJoinMidColumnName(); - String selfMidColumnName = midConditionDescription.getSelfMidColumnName(); - queryWrapper.select(joinMidColumnName + " as " + midConditionDescription.getJoinMidFieldName(), - selfMidColumnName + " as " + midConditionDescription.getSelfMidFieldName()); - queryWrapper.in(selfMidColumnName, selfFieldVals); - if(StringUtils.hasText(midConditionDescription.getCustomCondition())) { - queryWrapper.apply(midConditionDescription.getCustomCondition()); - } - - Class entity = (Class) midConditionDescription.getMidEntity(); - return MapperScanner.getMapperExecute(entity, mapper -> mapper.selectList(queryWrapper)); - } - - private void fullDataToBeanField(BEAN bean, FieldDescription fieldAnnotation, List dataList) { - - Object val; - - if (fieldAnnotation.isCollection()) { - val = dataList; - } else { - // 异常情况检查 - checkBindDataSize(bean.getClass().getName(), dataList.size(), fieldAnnotation.getFieldName()); - val = dataList.isEmpty() ? null : dataList.get(0); - } - - try { - fieldAnnotation.getSetMethod().invoke(bean, val); - } catch (IllegalAccessException | InvocationTargetException e) { - e.printStackTrace(); - } - } - - /** - * 检查绑定的数据结果,如果定义的类型为对象,但是却查出了多条数据,则报错 - */ - private void checkBindDataSize(String beanName, int dataListSize, String fieldName) { - - if (dataListSize > 1) { - String entityName = conditionSign.getJoinEntityClass().getName(); - throw new RuntimeException(beanName + "." + fieldName - + "关联" + entityName + "的数据条数大于1条"); - } - } - - private String getSelfFieldValFromBean(MidConditionDescription midConditionDescription, BEAN bean) { - - try { - Object val = midConditionDescription.getSelfFieldGetMethod().invoke(bean); - return Optional.ofNullable(val).map(Object::toString).orElse(""); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - public interface FillDataCallback { - - /** - * 只查询指定的字段,null或者长度0查询全部 - */ - default String[] selectColumns(List beans, - FieldDescription.ConditionSign conditionSign, - List> fieldAnnotationList) { - return null; - } - - /** - * 查询到结果之后,填充数据之前回调 - */ - default void fillBefore(Object bean, FieldDescription fieldAnnotation, List entities) { - - } - - /** - * 查询到结果之后,填充数据之前回调,该回调可以修改填充到Bean的结果 - */ - default List changeDataList(Object bean, FieldDescription fieldAnnotation, List entities) { - return entities; - } - } -} +package com.tangzc.mpe.bind.builder; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.tangzc.mpe.base.MapperScanner; +import com.tangzc.mpe.bind.metadata.FieldDescription; +import com.tangzc.mpe.bind.metadata.MidConditionDescription; +import com.tangzc.mpe.bind.metadata.OrderByDescription; +import lombok.AllArgsConstructor; +import org.springframework.util.StringUtils; + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * @author don + */ +@AllArgsConstructor(staticName = "newInstance") +public class ByMidResultBuilder { + + private final List beans; + private final FieldDescription.ConditionSign conditionSign; + private final List> fieldDescriptions; + private final FillDataCallback fillDataCallback; + + public void fillData() { + + // 中间表关联关系,仅限于一个条件,所以直接get(0) + MidConditionDescription midConditionDescription = conditionSign.getConditions().get(0); + + // > + Map> joinEntityMap = listEntitiesByCondition(midConditionDescription); + + // 循环填充每个bean + for (BEAN bean : beans) { + + String selfFieldVal = getSelfFieldValFromBean(midConditionDescription, bean); + List entities = joinEntityMap.getOrDefault(selfFieldVal, Collections.emptyList()); + + // 循环填充bean中的每个属性 + for (FieldDescription fieldAnnotation : fieldDescriptions) { + + List dataList = entities; + if (fillDataCallback != null) { + fillDataCallback.fillBefore(bean, fieldAnnotation, dataList); + dataList = fillDataCallback.changeDataList(bean, fieldAnnotation, dataList); + } + + fullDataToBeanField(bean, fieldAnnotation, dataList); + } + } + } + + /** + * 查询目标表的数据集合 + * + * @return > + */ + private Map> listEntitiesByCondition(MidConditionDescription midConditionDescription) { + + // 查询中间表符合要求的数据 + List midDataList = listMidData(midConditionDescription); + + // 对中间表数据进行分组,确定主表与从表的数据对应关系 + // > + Map> midDataListMap = midDataList.stream().collect(Collectors.groupingBy(midData -> { + try { + return midConditionDescription.getSelfMidFieldGetMethod().invoke(midData); + } catch (Exception e) { + throw new RuntimeException(e); + } + }, Collectors.mapping(midData -> { + try { + return midConditionDescription.getJoinMidFieldGetMethod().invoke(midData); + } catch (Exception e) { + throw new RuntimeException(e); + } + }, Collectors.toList()))); + + // 查询目标表数据 + Set joinMidFieldVals = midDataListMap.values().stream().flatMap(Collection::stream).collect(Collectors.toSet()); + List entities = listEntities(midConditionDescription, joinMidFieldVals); + // 对join表结果进行map映射 + Map entitiesMap = entities.stream().collect(Collectors.toMap(ent -> { + try { + return midConditionDescription.getJoinFieldGetMethod().invoke(ent); + } catch (Exception e) { + throw new RuntimeException(e); + } + }, Function.identity())); + + // 集合中间表数据与join表数据 + Map> dataMap = new HashMap<>(midDataListMap.size()); + midDataListMap.forEach((selfVal, joinValList) -> + dataMap.put(selfVal.toString(), + joinValList.stream().map(entitiesMap::get) + .filter(Objects::nonNull) + .collect(Collectors.toList()) + ) + ); + return dataMap; + } + + /** + * 查询join表的数据 + */ + private List listEntities(MidConditionDescription midConditionDescription, Set joinMidFieldVals) { + + if (joinMidFieldVals.isEmpty()) { + return Collections.emptyList(); + } + + QueryWrapper queryWrapper = new QueryWrapper<>(); + // 查询某些列值 + String[] selectColumns = fillDataCallback.selectColumns(beans, conditionSign, fieldDescriptions); + if (selectColumns != null && selectColumns.length > 0) { + queryWrapper.select(selectColumns); + } + // 添加主要条件 + queryWrapper.in(midConditionDescription.getJoinColumnName(), joinMidFieldVals); + // 自定义条件 + queryWrapper.apply(StringUtils.hasText(conditionSign.getCustomCondition()), conditionSign.getCustomCondition()); + // 排序 + for (OrderByDescription orderBy : conditionSign.getOrderBys()) { + queryWrapper.orderBy(true, orderBy.isAsc(), orderBy.getColumnName()); + } + // last sql + queryWrapper.last(conditionSign.getLast()); + + Class joinEntityClass = conditionSign.getJoinEntityClass(); + return MapperScanner.getMapperExecute(joinEntityClass, mapper -> mapper.selectList(queryWrapper)); + } + + /** + * 查询中间表的数据 + */ + private List listMidData(MidConditionDescription midConditionDescription) { + + // 获取bean集合中自身字段值的集合 + List selfFieldVals = new ArrayList<>(); + try { + for (BEAN bean : beans) { + selfFieldVals.add(midConditionDescription.getSelfFieldGetMethod().invoke(bean)); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + + if (selfFieldVals.isEmpty()) { + return Collections.emptyList(); + } + + // 构建查询器 + QueryWrapper queryWrapper = new QueryWrapper<>(); + // 仅仅查询关联关系的两列(对于性能提升只在中间表列数很多的情况下有意义) + String joinMidColumnName = midConditionDescription.getJoinMidColumnName(); + String selfMidColumnName = midConditionDescription.getSelfMidColumnName(); + queryWrapper.select(joinMidColumnName, selfMidColumnName); + queryWrapper.in(selfMidColumnName, selfFieldVals); + if(StringUtils.hasText(midConditionDescription.getCustomCondition())) { + queryWrapper.apply(midConditionDescription.getCustomCondition()); + } + + Class entity = (Class) midConditionDescription.getMidEntity(); + return MapperScanner.getMapperExecute(entity, mapper -> mapper.selectList(queryWrapper)); + } + + private void fullDataToBeanField(BEAN bean, FieldDescription fieldAnnotation, List dataList) { + + Object val; + + if (fieldAnnotation.isCollection()) { + val = dataList; + } else { + // 异常情况检查 + checkBindDataSize(bean.getClass().getName(), dataList.size(), fieldAnnotation.getFieldName()); + val = dataList.isEmpty() ? null : dataList.get(0); + } + + try { + fieldAnnotation.getSetMethod().invoke(bean, val); + } catch (IllegalAccessException | InvocationTargetException e) { + e.printStackTrace(); + } + } + + /** + * 检查绑定的数据结果,如果定义的类型为对象,但是却查出了多条数据,则报错 + */ + private void checkBindDataSize(String beanName, int dataListSize, String fieldName) { + + if (dataListSize > 1) { + String entityName = conditionSign.getJoinEntityClass().getName(); + throw new RuntimeException(beanName + "." + fieldName + + "关联" + entityName + "的数据条数大于1条"); + } + } + + private String getSelfFieldValFromBean(MidConditionDescription midConditionDescription, BEAN bean) { + + try { + Object val = midConditionDescription.getSelfFieldGetMethod().invoke(bean); + return Optional.ofNullable(val).map(Object::toString).orElse(""); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public interface FillDataCallback { + + /** + * 只查询指定的字段,null或者长度0查询全部 + */ + default String[] selectColumns(List beans, + FieldDescription.ConditionSign conditionSign, + List> fieldAnnotationList) { + return null; + } + + /** + * 查询到结果之后,填充数据之前回调 + */ + default void fillBefore(Object bean, FieldDescription fieldAnnotation, List entities) { + + } + + /** + * 查询到结果之后,填充数据之前回调,该回调可以修改填充到Bean的结果 + */ + default List changeDataList(Object bean, FieldDescription fieldAnnotation, List entities) { + return entities; + } + } +} -- Gitee