001/* 002 * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package com.mybatisflex.core.relation; 017 018import com.mybatisflex.core.exception.FlexExceptions; 019import com.mybatisflex.core.query.QueryWrapper; 020import com.mybatisflex.core.row.Row; 021import com.mybatisflex.core.util.*; 022 023import java.lang.reflect.Field; 024import java.util.*; 025 026class ToManyRelation<SelfEntity> extends AbstractRelation<SelfEntity> { 027 028 protected String mapKeyField; 029 protected FieldWrapper mapKeyFieldWrapper; 030 protected String orderBy; 031 protected long limit = 0; 032 protected String selfValueSplitBy; 033 034 035 public ToManyRelation(String selfField, String targetSchema, String targetTable, String targetField, String valueField, 036 String joinTable, String joinSelfColumn, String joinTargetColumn, 037 String dataSource, Class<SelfEntity> selfEntityClass, Field relationField, 038 String extraCondition, String[] selectColumns) { 039 super(selfField, targetSchema, targetTable, targetField, valueField, 040 joinTable, joinSelfColumn, joinTargetColumn, 041 dataSource, selfEntityClass, relationField, 042 extraCondition, selectColumns 043 ); 044 } 045 046 /** 047 * 构建查询目标对象的 QueryWrapper 048 * 049 * @param targetValues 条件的值 050 * @return QueryWrapper 051 */ 052 @Override 053 public QueryWrapper buildQueryWrapper(Set<Object> targetValues) { 054 if (StringUtil.isNotBlank(selfValueSplitBy) && CollectionUtil.isNotEmpty(targetValues)) { 055 Set<Object> newTargetValues = new HashSet<>(); 056 for (Object targetValue : targetValues) { 057 if (targetValue == null) { 058 continue; 059 } 060 if (!(targetValue instanceof String)) { 061 throw FlexExceptions.wrap("split field only support String type, but current type is: \"" + targetValue.getClass().getName() + "\""); 062 } 063 String[] splitValues = ((String) targetValue).split(selfValueSplitBy); 064 for (String splitValue : splitValues) { 065 //优化分割后的数据类型(防止在数据库查询时候出现隐式转换) 066 newTargetValues.add(ConvertUtil.convert(splitValue, targetFieldWrapper.getFieldType())); 067 } 068 } 069 targetValues = newTargetValues; 070 } 071 return super.buildQueryWrapper(targetValues); 072 } 073 074 075 @Override 076 public void customizeQueryWrapper(QueryWrapper queryWrapper) { 077 if (StringUtil.isNotBlank(orderBy)) { 078 queryWrapper.orderBy(orderBy); 079 } 080 081 if (limit > 0) { 082 queryWrapper.limit(limit); 083 } 084 } 085 086 @SuppressWarnings("rawtypes") 087 @Override 088 public void join(List<SelfEntity> selfEntities, List<?> targetObjectList, List<Row> mappingRows) { 089 selfEntities.forEach(selfEntity -> { 090 Object selfValue = selfFieldWrapper.get(selfEntity); 091 if (selfValue != null) { 092 selfValue = selfValue.toString(); 093 Set<String> targetMappingValues = new HashSet<>(); 094 if (mappingRows != null) { 095 for (Row mappingRow : mappingRows) { 096 if (selfValue.equals(String.valueOf(mappingRow.getIgnoreCase(joinSelfColumn)))) { 097 Object joinValue = mappingRow.getIgnoreCase(joinTargetColumn); 098 if (joinValue != null) { 099 targetMappingValues.add(joinValue.toString()); 100 } 101 } 102 } 103 } else { 104 if (StringUtil.isNotBlank(selfValueSplitBy)) { 105 String[] splitValues = ((String) selfValue).split(selfValueSplitBy); 106 targetMappingValues.addAll(Arrays.asList(splitValues)); 107 } else { 108 targetMappingValues.add((String) selfValue); 109 } 110 } 111 112 if (targetMappingValues.isEmpty()) { 113 return; 114 } 115 116 Class<?> fieldType = relationFieldWrapper.getFieldType(); 117 //map 118 if (Map.class.isAssignableFrom(fieldType)) { 119 Class<?> wrapType = getMapWrapType(fieldType); 120 Map map = (Map) ClassUtil.newInstance(wrapType); 121 for (Object targetObject : targetObjectList) { 122 Object targetValue = targetFieldWrapper.get(targetObject); 123 if (targetValue != null && targetMappingValues.contains(targetValue.toString())) { 124 Object keyValue = mapKeyFieldWrapper.get(targetObject); 125 Object needKeyValue = ConvertUtil.convert(keyValue, relationFieldWrapper.getKeyType()); 126 map.put(needKeyValue, targetObject); 127 } 128 } 129 relationFieldWrapper.set(map, selfEntity); 130 } 131 //集合 132 else { 133 Class<?> wrapType = MapperUtil.getCollectionWrapType(fieldType); 134 Collection collection = (Collection) ClassUtil.newInstance(wrapType); 135 for (Object targetObject : targetObjectList) { 136 Object targetValue = targetFieldWrapper.get(targetObject); 137 if (targetValue != null && targetMappingValues.contains(targetValue.toString())) { 138 if (onlyQueryValueField) { 139 //仅绑定某个字段 140 collection.add(FieldWrapper.of(targetObject.getClass(), valueField).get(targetObject)); 141 } else { 142 collection.add(targetObject); 143 } 144 } 145 } 146 relationFieldWrapper.set(collection, selfEntity); 147 } 148 } 149 }); 150 } 151 152 public void setMapKeyField(String mapKeyField) { 153 this.mapKeyField = mapKeyField; 154 if (StringUtil.isNotBlank(mapKeyField)) { 155 this.mapKeyFieldWrapper = FieldWrapper.of(targetEntityClass, mapKeyField); 156 } else { 157 if (Map.class.isAssignableFrom(relationFieldWrapper.getFieldType())) { 158 throw FlexExceptions.wrap("Please config mapKeyField for map field: " + relationFieldWrapper.getField()); 159 } 160 } 161 } 162 163 public static Class<? extends Map> getMapWrapType(Class<?> type) { 164 if (ClassUtil.canInstance(type.getModifiers())) { 165 return (Class<? extends Map>) type; 166 } 167 168 return HashMap.class; 169 } 170 171}