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 */ 016 017package com.mybatisflex.core.field; 018 019import com.mybatisflex.core.BaseMapper; 020import com.mybatisflex.core.exception.FlexExceptions; 021import com.mybatisflex.core.query.QueryWrapper; 022import com.mybatisflex.core.row.Row; 023import com.mybatisflex.core.util.ClassUtil; 024import com.mybatisflex.core.util.CollectionUtil; 025 026import java.lang.reflect.Array; 027import java.util.*; 028 029/** 030 * 属性查询管理。 031 * 032 * @author 王帅 033 * @since 2023-07-15 034 */ 035public class FieldQueryManager { 036 037 private FieldQueryManager() { 038 } 039 040 public static void queryFields(BaseMapper<?> mapper, Collection<?> entities, Map<String, FieldQuery> fieldQueryMap) { 041 for (Object entity : entities) { 042 043 if (entity == null) { 044 continue; 045 } 046 047 String className = ClassUtil.getUsefulClass(entity.getClass()).getName(); 048 049 fieldQueryMap.forEach((key, fieldQuery) -> { 050 // 不是当前类的内容 051 if (!key.startsWith(className + "#")) { 052 return; 053 } 054 055 @SuppressWarnings("unchecked") 056 QueryWrapper queryWrapper = fieldQuery.getQueryBuilder().build(entity); 057 058 // QueryWrapper 为 null 值时,不进行属性查询 059 if (queryWrapper == null) { 060 return; 061 } 062 063 Class<?> filedType = fieldQuery.getFieldWrapper().getFieldType(); 064 Object value; 065 066 if (Collection.class.isAssignableFrom(filedType)) { 067 Class<?> mappingType = fieldQuery.getFieldWrapper().getMappingType(); 068 List<?> list = mapper.selectListByQueryAs(queryWrapper, mappingType); 069 // 转换成 Collection 子类,或者空 Collection 对象,避免 NPE 070 value = getCollectionValue(filedType, list); 071 // 循环查询泛型实体类 072 if ((!Number.class.isAssignableFrom(mappingType) 073 || !String.class.isAssignableFrom(mappingType) 074 || !Map.class.isAssignableFrom(mappingType)) 075 && !fieldQuery.isPrevent()) { 076 queryFields(mapper, (Collection<?>) value, fieldQueryMap); 077 } 078 } else if (Map.class.isAssignableFrom(filedType)) { 079 List<Row> rows = mapper.selectRowsByQuery(queryWrapper); 080 // 转换成 Map 子类,或者空 Map 对象,避免 NPE 081 if (rows != null && !rows.isEmpty() && rows.get(0) != null) { 082 value = getMapValue(filedType, rows.get(0)); 083 } else { 084 value = new HashMap<>(); 085 } 086 } else if (filedType.isArray()) { 087 Class<?> componentType = filedType.getComponentType(); 088 List<?> objects = mapper.selectListByQueryAs(queryWrapper, componentType); 089 value = getArrayValue(componentType, objects); 090 } else { 091 value = mapper.selectOneByQueryAs(queryWrapper, filedType); 092 // 循环查询嵌套类 093 if (!fieldQuery.isPrevent()) { 094 queryFields(mapper, Collections.singletonList(value), fieldQueryMap); 095 } 096 } 097 // 属性查询出来的值不为 null 时,为属性设置值 098 if (value != null) { 099 fieldQuery.getFieldWrapper().set(value, entity); 100 } 101 }); 102 } 103 } 104 105 106 @SuppressWarnings({"rawtypes", "unchecked"}) 107 private static Object getCollectionValue(Class<?> fieldType, Collection value) { 108 if (value == null) { 109 if (fieldType == List.class) { 110 return Collections.emptyList(); 111 } else if (fieldType == Set.class) { 112 return Collections.emptySet(); 113 } 114 // avoid NPE 115 return ClassUtil.newInstance(fieldType); 116 } 117 118 if (ClassUtil.canInstance(fieldType.getModifiers())) { 119 Collection collection = (Collection) ClassUtil.newInstance(fieldType); 120 collection.addAll(value); 121 return collection; 122 } 123 124 if (List.class.isAssignableFrom(fieldType)) { 125 return value; 126 } 127 128 if (Set.class.isAssignableFrom(fieldType)) { 129 return new HashSet<>(value); 130 } 131 132 throw FlexExceptions.wrap("Unsupported collection type: " + fieldType); 133 } 134 135 @SuppressWarnings({"rawtypes", "unchecked"}) 136 private static Object getMapValue(Class<?> fieldType, Map value) { 137 if (ClassUtil.canInstance(fieldType.getModifiers())) { 138 Map map = (Map) ClassUtil.newInstance(fieldType); 139 map.putAll(value); 140 return map; 141 } 142 143 return new HashMap<>(value); 144 } 145 146 @SuppressWarnings("unchecked") 147 private static <T> Object getArrayValue(Class<?> componentType, List<T> list) { 148 if (CollectionUtil.isEmpty(list)) { 149 return Array.newInstance(componentType, 0); 150 } 151 152 T[] array = (T[]) Array.newInstance(componentType, list.size()); 153 154 for (int rows = 0; rows < list.size(); rows++) { 155 array[rows] = list.get(rows); 156 } 157 158 return array; 159 } 160 161}