mirror of
https://gitee.com/mybatis-flex/mybatis-flex.git
synced 2025-12-07 00:58:24 +08:00
feat: 1 分页查询添加关联字段查询;2 添加 FieldWrapper 使得关联字段查询拥有更高的性能;3 添加 ClassUtil.getFirstMethod 方法;4 优化 EnumWrapper 使之逻辑更加清晰简单;4 字段子查询不在需要配置 type
This commit is contained in:
parent
cd2ff939e5
commit
b9d3a6e16c
@ -29,7 +29,6 @@ QueryWrapper queryWrapper = QueryWrapper.create()
|
|||||||
List<Article> articles = mapper.selectListByQuery(queryWrapper
|
List<Article> articles = mapper.selectListByQuery(queryWrapper
|
||||||
, fieldQueryBuilder -> fieldQueryBuilder
|
, fieldQueryBuilder -> fieldQueryBuilder
|
||||||
.field(Article::getCategories) // 或者 .field("categories")
|
.field(Article::getCategories) // 或者 .field("categories")
|
||||||
.type(Category.class) //非集合,自动读取 type,可以不指定 type
|
|
||||||
.queryWrapper(article -> QueryWrapper.create()
|
.queryWrapper(article -> QueryWrapper.create()
|
||||||
.select().from(CATEGORY)
|
.select().from(CATEGORY)
|
||||||
.where(CATEGORY.id.in(
|
.where(CATEGORY.id.in(
|
||||||
|
|||||||
@ -19,7 +19,6 @@ package com.mybatisflex.codegen.test;
|
|||||||
import com.mybatisflex.codegen.Generator;
|
import com.mybatisflex.codegen.Generator;
|
||||||
import com.mybatisflex.codegen.config.GlobalConfig;
|
import com.mybatisflex.codegen.config.GlobalConfig;
|
||||||
import com.zaxxer.hikari.HikariDataSource;
|
import com.zaxxer.hikari.HikariDataSource;
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.util.function.UnaryOperator;
|
import java.util.function.UnaryOperator;
|
||||||
|
|
||||||
@ -82,7 +81,7 @@ public class GeneratorTest {
|
|||||||
generator.generate();
|
generator.generate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
// @Test
|
||||||
public void testCodeGen2() {
|
public void testCodeGen2() {
|
||||||
//配置数据源
|
//配置数据源
|
||||||
HikariDataSource dataSource = new HikariDataSource();
|
HikariDataSource dataSource = new HikariDataSource();
|
||||||
|
|||||||
@ -24,14 +24,9 @@ import com.mybatisflex.core.provider.EntitySqlProvider;
|
|||||||
import com.mybatisflex.core.query.*;
|
import com.mybatisflex.core.query.*;
|
||||||
import com.mybatisflex.core.table.TableInfo;
|
import com.mybatisflex.core.table.TableInfo;
|
||||||
import com.mybatisflex.core.table.TableInfoFactory;
|
import com.mybatisflex.core.table.TableInfoFactory;
|
||||||
import com.mybatisflex.core.util.CollectionUtil;
|
import com.mybatisflex.core.util.*;
|
||||||
import com.mybatisflex.core.util.ConvertUtil;
|
|
||||||
import com.mybatisflex.core.util.ObjectUtil;
|
|
||||||
import com.mybatisflex.core.util.StringUtil;
|
|
||||||
import org.apache.ibatis.annotations.*;
|
import org.apache.ibatis.annotations.*;
|
||||||
import org.apache.ibatis.builder.annotation.ProviderContext;
|
import org.apache.ibatis.builder.annotation.ProviderContext;
|
||||||
import org.apache.ibatis.reflection.MetaObject;
|
|
||||||
import org.apache.ibatis.reflection.SystemMetaObject;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@ -426,29 +421,24 @@ public interface BaseMapper<T> {
|
|||||||
consumer.accept(fieldQueryBuilder);
|
consumer.accept(fieldQueryBuilder);
|
||||||
FieldQuery fieldQuery = fieldQueryBuilder.build();
|
FieldQuery fieldQuery = fieldQueryBuilder.build();
|
||||||
QueryWrapper childQuery = fieldQuery.getQueryWrapper();
|
QueryWrapper childQuery = fieldQuery.getQueryWrapper();
|
||||||
MetaObject entityMetaObject = SystemMetaObject.forObject(entity);
|
|
||||||
Class<?> setterType = entityMetaObject.getSetterType(fieldQuery.getField());
|
|
||||||
|
|
||||||
Class<?> mappingType = fieldQuery.getMappingType();
|
FieldWrapper fieldWrapper = FieldWrapper.of(entity.getClass(), fieldQuery.getField());
|
||||||
if (mappingType == null) {
|
if (fieldWrapper == null) {
|
||||||
if (setterType.isAssignableFrom(Collection.class)) {
|
throw new IllegalStateException("Can not find field \"" + fieldQuery.getField() + "\" in class: " + entity.getClass());
|
||||||
throw new IllegalStateException("Mapping Type can not be null for query Many.");
|
|
||||||
} else if (setterType.isArray()) {
|
|
||||||
mappingType = setterType.getComponentType();
|
|
||||||
} else {
|
|
||||||
mappingType = setterType;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Class<?> fieldType = fieldWrapper.getFieldType();
|
||||||
|
Class<?> mappingType = fieldWrapper.getMappingType();
|
||||||
|
|
||||||
Object value;
|
Object value;
|
||||||
try {
|
try {
|
||||||
MappedStatementTypes.setCurrentType(mappingType);
|
MappedStatementTypes.setCurrentType(mappingType);
|
||||||
if (setterType.isAssignableFrom(List.class)) {
|
if (fieldType.isAssignableFrom(List.class)) {
|
||||||
value = selectListByQueryAs(childQuery, mappingType);
|
value = selectListByQueryAs(childQuery, mappingType);
|
||||||
} else if (setterType.isAssignableFrom(Set.class)) {
|
} else if (fieldType.isAssignableFrom(Set.class)) {
|
||||||
value = selectListByQueryAs(childQuery, mappingType);
|
value = selectListByQueryAs(childQuery, mappingType);
|
||||||
value = new HashSet<>((Collection<?>) value);
|
value = new HashSet<>((Collection<?>) value);
|
||||||
} else if (setterType.isArray()) {
|
} else if (fieldType.isArray()) {
|
||||||
value = selectListByQueryAs(childQuery, mappingType);
|
value = selectListByQueryAs(childQuery, mappingType);
|
||||||
value = ((List<?>) value).toArray();
|
value = ((List<?>) value).toArray();
|
||||||
} else {
|
} else {
|
||||||
@ -457,7 +447,7 @@ public interface BaseMapper<T> {
|
|||||||
} finally {
|
} finally {
|
||||||
MappedStatementTypes.clear();
|
MappedStatementTypes.clear();
|
||||||
}
|
}
|
||||||
entityMetaObject.setValue(fieldQuery.getField(), value);
|
fieldWrapper.set(value, entity);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -498,29 +488,24 @@ public interface BaseMapper<T> {
|
|||||||
FieldQuery fieldQuery = fieldQueryBuilder.build();
|
FieldQuery fieldQuery = fieldQueryBuilder.build();
|
||||||
QueryWrapper childQuery = fieldQuery.getQueryWrapper();
|
QueryWrapper childQuery = fieldQuery.getQueryWrapper();
|
||||||
|
|
||||||
MetaObject entityMetaObject = SystemMetaObject.forObject(entity);
|
FieldWrapper fieldWrapper = FieldWrapper.of(entity.getClass(), fieldQuery.getField());
|
||||||
Class<?> setterType = entityMetaObject.getSetterType(fieldQuery.getField());
|
|
||||||
|
|
||||||
Class<?> mappingType = fieldQuery.getMappingType();
|
if (fieldWrapper == null) {
|
||||||
if (mappingType == null) {
|
throw new IllegalStateException("Can not find field \"" + fieldQuery.getField() + "\" in class: " + entity.getClass());
|
||||||
if (setterType.isAssignableFrom(Collection.class)) {
|
|
||||||
throw new IllegalStateException("Mapping Type can not be null for query Many.");
|
|
||||||
} else if (setterType.isArray()) {
|
|
||||||
mappingType = setterType.getComponentType();
|
|
||||||
} else {
|
|
||||||
mappingType = setterType;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Class<?> fieldType = fieldWrapper.getFieldType();
|
||||||
|
Class<?> mappingType = fieldWrapper.getMappingType();
|
||||||
|
|
||||||
Object value;
|
Object value;
|
||||||
try {
|
try {
|
||||||
MappedStatementTypes.setCurrentType(mappingType);
|
MappedStatementTypes.setCurrentType(mappingType);
|
||||||
if (setterType.isAssignableFrom(List.class)) {
|
if (fieldType.isAssignableFrom(List.class)) {
|
||||||
value = selectListByQueryAs(childQuery, mappingType);
|
value = selectListByQueryAs(childQuery, mappingType);
|
||||||
} else if (setterType.isAssignableFrom(Set.class)) {
|
} else if (fieldType.isAssignableFrom(Set.class)) {
|
||||||
value = selectListByQueryAs(childQuery, mappingType);
|
value = selectListByQueryAs(childQuery, mappingType);
|
||||||
value = new HashSet<>((Collection<?>) value);
|
value = new HashSet<>((Collection<?>) value);
|
||||||
} else if (setterType.isArray()) {
|
} else if (fieldType.isArray()) {
|
||||||
value = selectListByQueryAs(childQuery, mappingType);
|
value = selectListByQueryAs(childQuery, mappingType);
|
||||||
value = ((List<?>) value).toArray();
|
value = ((List<?>) value).toArray();
|
||||||
} else {
|
} else {
|
||||||
@ -529,9 +514,7 @@ public interface BaseMapper<T> {
|
|||||||
} finally {
|
} finally {
|
||||||
MappedStatementTypes.clear();
|
MappedStatementTypes.clear();
|
||||||
}
|
}
|
||||||
|
fieldWrapper.set(value, entity);
|
||||||
|
|
||||||
entityMetaObject.setValue(fieldQuery.getField(), value);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -694,12 +677,12 @@ public interface BaseMapper<T> {
|
|||||||
* @param queryWrapper 查询条件
|
* @param queryWrapper 查询条件
|
||||||
* @return page 数据
|
* @return page 数据
|
||||||
*/
|
*/
|
||||||
default Page<T> paginate(Page<T> page, QueryWrapper queryWrapper) {
|
default Page<T> paginate(Page<T> page, QueryWrapper queryWrapper, Consumer<FieldQueryBuilder<T>>... consumers) {
|
||||||
return paginateAs(page, queryWrapper, null);
|
return paginateAs(page, queryWrapper, null, consumers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
default <R> Page<R> paginateAs(Page<R> page, QueryWrapper queryWrapper, Class<R> asType) {
|
default <R> Page<R> paginateAs(Page<R> page, QueryWrapper queryWrapper, Class<R> asType, Consumer<FieldQueryBuilder<R>>... consumers) {
|
||||||
List<QueryColumn> selectColumns = CPI.getSelectColumns(queryWrapper);
|
List<QueryColumn> selectColumns = CPI.getSelectColumns(queryWrapper);
|
||||||
List<QueryOrderBy> orderBys = CPI.getOrderBys(queryWrapper);
|
List<QueryOrderBy> orderBys = CPI.getOrderBys(queryWrapper);
|
||||||
|
|
||||||
@ -780,7 +763,7 @@ public interface BaseMapper<T> {
|
|||||||
// 调用内部方法,不走代理,需要主动设置 MappedStatementType
|
// 调用内部方法,不走代理,需要主动设置 MappedStatementType
|
||||||
// fixed https://gitee.com/mybatis-flex/mybatis-flex/issues/I73BP6
|
// fixed https://gitee.com/mybatis-flex/mybatis-flex/issues/I73BP6
|
||||||
MappedStatementTypes.setCurrentType(asType);
|
MappedStatementTypes.setCurrentType(asType);
|
||||||
List<R> records = selectListByQueryAs(queryWrapper, asType);
|
List<R> records = selectListByQueryAs(queryWrapper, asType, consumers);
|
||||||
page.setRecords(records);
|
page.setRecords(records);
|
||||||
} finally {
|
} finally {
|
||||||
MappedStatementTypes.clear();
|
MappedStatementTypes.clear();
|
||||||
|
|||||||
@ -22,7 +22,7 @@ import java.io.Serializable;
|
|||||||
public class FieldQuery implements Serializable {
|
public class FieldQuery implements Serializable {
|
||||||
|
|
||||||
private String field;
|
private String field;
|
||||||
private Class<?> mappingType;
|
// private Class<?> mappingType;
|
||||||
private QueryWrapper queryWrapper;
|
private QueryWrapper queryWrapper;
|
||||||
|
|
||||||
public String getField() {
|
public String getField() {
|
||||||
@ -33,13 +33,13 @@ public class FieldQuery implements Serializable {
|
|||||||
this.field = field;
|
this.field = field;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class<?> getMappingType() {
|
// public Class<?> getMappingType() {
|
||||||
return mappingType;
|
// return mappingType;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
public void setMappingType(Class<?> mappingType) {
|
// public void setMappingType(Class<?> mappingType) {
|
||||||
this.mappingType = mappingType;
|
// this.mappingType = mappingType;
|
||||||
}
|
// }
|
||||||
|
|
||||||
public QueryWrapper getQueryWrapper() {
|
public QueryWrapper getQueryWrapper() {
|
||||||
return queryWrapper;
|
return queryWrapper;
|
||||||
|
|||||||
@ -38,10 +38,10 @@ public class FieldQueryBuilder<T> implements Serializable {
|
|||||||
return field(LambdaUtil.getFieldName(fn));
|
return field(LambdaUtil.getFieldName(fn));
|
||||||
}
|
}
|
||||||
|
|
||||||
public FieldQueryBuilder<T> type(Class<?> mappingType){
|
// public FieldQueryBuilder<T> type(Class<?> mappingType){
|
||||||
fieldQuery.setMappingType(mappingType);
|
// fieldQuery.setMappingType(mappingType);
|
||||||
return this;
|
// return this;
|
||||||
}
|
// }
|
||||||
|
|
||||||
public FieldQueryBuilder<T> queryWrapper(QueryBuilder<T> fun){
|
public FieldQueryBuilder<T> queryWrapper(QueryBuilder<T> fun){
|
||||||
fieldQuery.setQueryWrapper(fun.build(entity));
|
fieldQuery.setQueryWrapper(fun.build(entity));
|
||||||
|
|||||||
@ -181,17 +181,23 @@ public class ClassUtil {
|
|||||||
|
|
||||||
public static List<Field> getAllFields(Class<?> cl) {
|
public static List<Field> getAllFields(Class<?> cl) {
|
||||||
List<Field> fields = new ArrayList<>();
|
List<Field> fields = new ArrayList<>();
|
||||||
doGetFields(cl, fields, null);
|
doGetFields(cl, fields, null, false);
|
||||||
return fields;
|
return fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Field> getAllFields(Class<?> cl, Predicate<Field> predicate) {
|
public static List<Field> getAllFields(Class<?> cl, Predicate<Field> predicate) {
|
||||||
List<Field> fields = new ArrayList<>();
|
List<Field> fields = new ArrayList<>();
|
||||||
doGetFields(cl, fields, predicate);
|
doGetFields(cl, fields, predicate, false);
|
||||||
return fields;
|
return fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void doGetFields(Class<?> cl, List<Field> fields, Predicate<Field> predicate) {
|
public static Field getFirstField(Class<?> cl, Predicate<Field> predicate) {
|
||||||
|
List<Field> fields = new ArrayList<>();
|
||||||
|
doGetFields(cl, fields, predicate, true);
|
||||||
|
return fields.isEmpty() ? null : fields.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void doGetFields(Class<?> cl, List<Field> fields, Predicate<Field> predicate, boolean firstOnly) {
|
||||||
if (cl == null || cl == Object.class) {
|
if (cl == null || cl == Object.class) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -200,26 +206,39 @@ public class ClassUtil {
|
|||||||
for (Field declaredField : declaredFields) {
|
for (Field declaredField : declaredFields) {
|
||||||
if (predicate == null || predicate.test(declaredField)) {
|
if (predicate == null || predicate.test(declaredField)) {
|
||||||
fields.add(declaredField);
|
fields.add(declaredField);
|
||||||
|
if (firstOnly) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
doGetFields(cl.getSuperclass(), fields, predicate);
|
if (firstOnly && !fields.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
doGetFields(cl.getSuperclass(), fields, predicate, firstOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Method> getAllMethods(Class<?> cl) {
|
public static List<Method> getAllMethods(Class<?> cl) {
|
||||||
List<Method> methods = new ArrayList<>();
|
List<Method> methods = new ArrayList<>();
|
||||||
doGetMethods(cl, methods, null);
|
doGetMethods(cl, methods, null, false);
|
||||||
return methods;
|
return methods;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Method> getAllMethods(Class<?> cl, Predicate<Method> predicate) {
|
public static List<Method> getAllMethods(Class<?> cl, Predicate<Method> predicate) {
|
||||||
List<Method> methods = new ArrayList<>();
|
List<Method> methods = new ArrayList<>();
|
||||||
doGetMethods(cl, methods, predicate);
|
doGetMethods(cl, methods, predicate, false);
|
||||||
return methods;
|
return methods;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Method getFirstMethod(Class<?> cl, Predicate<Method> predicate) {
|
||||||
|
List<Method> methods = new ArrayList<>();
|
||||||
|
doGetMethods(cl, methods, predicate, true);
|
||||||
|
return methods.isEmpty() ? null : methods.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
private static void doGetMethods(Class<?> cl, List<Method> methods, Predicate<Method> predicate) {
|
|
||||||
|
private static void doGetMethods(Class<?> cl, List<Method> methods, Predicate<Method> predicate, boolean firstOnly) {
|
||||||
if (cl == null || cl == Object.class) {
|
if (cl == null || cl == Object.class) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -228,10 +247,17 @@ public class ClassUtil {
|
|||||||
for (Method method : declaredMethods) {
|
for (Method method : declaredMethods) {
|
||||||
if (predicate == null || predicate.test(method)) {
|
if (predicate == null || predicate.test(method)) {
|
||||||
methods.add(method);
|
methods.add(method);
|
||||||
|
if (firstOnly) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
doGetMethods(cl.getSuperclass(), methods, predicate);
|
if (firstOnly && !methods.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
doGetMethods(cl.getSuperclass(), methods, predicate, firstOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T> Class<T> getJdkProxySuperClass(Class<T> clazz) {
|
private static <T> Class<T> getJdkProxySuperClass(Class<T> clazz) {
|
||||||
|
|||||||
@ -22,7 +22,6 @@ import org.apache.ibatis.util.MapUtil;
|
|||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
@ -45,31 +44,30 @@ public class EnumWrapper<E extends Enum<E>> {
|
|||||||
public EnumWrapper(Class<E> enumClass) {
|
public EnumWrapper(Class<E> enumClass) {
|
||||||
this.enumClass = enumClass;
|
this.enumClass = enumClass;
|
||||||
|
|
||||||
List<Field> allFields = ClassUtil.getAllFields(enumClass, field -> field.getAnnotation(EnumValue.class) != null);
|
Field enumValueField = ClassUtil.getFirstField(enumClass, field -> field.getAnnotation(EnumValue.class) != null);
|
||||||
if (!allFields.isEmpty()) {
|
if (enumValueField != null) {
|
||||||
hasEnumValueAnnotation = true;
|
hasEnumValueAnnotation = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasEnumValueAnnotation) {
|
if (hasEnumValueAnnotation) {
|
||||||
Field field = allFields.get(0);
|
String fieldGetterName = "get" + StringUtil.firstCharToUpperCase(enumValueField.getName());
|
||||||
|
|
||||||
String fieldGetterName = "get" + StringUtil.firstCharToUpperCase(field.getName());
|
Method getterMethod = ClassUtil.getFirstMethod(enumClass, method -> {
|
||||||
List<Method> allMethods = ClassUtil.getAllMethods(enumClass, method -> {
|
|
||||||
String methodName = method.getName();
|
String methodName = method.getName();
|
||||||
return methodName.equals(fieldGetterName);
|
return methodName.equals(fieldGetterName) && Modifier.isPublic(method.getModifiers());
|
||||||
});
|
});
|
||||||
|
|
||||||
enumPropertyType = ClassUtil.wrap(field.getType());
|
enumPropertyType = ClassUtil.wrap(enumValueField.getType());
|
||||||
enums = enumClass.getEnumConstants();
|
enums = enumClass.getEnumConstants();
|
||||||
|
|
||||||
if (allMethods.isEmpty()) {
|
if (getterMethod != null) {
|
||||||
if (Modifier.isPublic(field.getModifiers())) {
|
if (Modifier.isPublic(enumValueField.getModifiers())) {
|
||||||
property = field;
|
property = enumValueField;
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException("Can not find \"" + fieldGetterName + "()\" method in enum: " + enumClass.getName());
|
throw new IllegalStateException("Can not find \"" + fieldGetterName + "()\" method in enum: " + enumClass.getName());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
getter = allMethods.get(0);
|
getter = getterMethod;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,103 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||||
|
* <p>
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* <p>
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* <p>
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.mybatisflex.core.util;
|
||||||
|
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
public class FieldWrapper {
|
||||||
|
|
||||||
|
public static Map<Class<?>, Map<String, FieldWrapper>> cache = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private Class<?> fieldType;
|
||||||
|
private Class<?> mappingType;
|
||||||
|
private Method method;
|
||||||
|
|
||||||
|
public static FieldWrapper of(Class<?> clazz, String fieldName) {
|
||||||
|
Map<String, FieldWrapper> wrapperMap = cache.get(clazz);
|
||||||
|
if (wrapperMap == null) {
|
||||||
|
synchronized (clazz) {
|
||||||
|
if (wrapperMap == null) {
|
||||||
|
wrapperMap = new ConcurrentHashMap<>();
|
||||||
|
cache.put(clazz, wrapperMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FieldWrapper fieldWrapper = wrapperMap.get(fieldName);
|
||||||
|
if (fieldWrapper == null) {
|
||||||
|
synchronized (clazz) {
|
||||||
|
fieldWrapper = wrapperMap.get(fieldName);
|
||||||
|
if (fieldWrapper == null) {
|
||||||
|
Field findField = ClassUtil.getFirstField(clazz, field -> field.getName().equals(fieldName));
|
||||||
|
if (findField == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldWrapper = new FieldWrapper();
|
||||||
|
fieldWrapper.fieldType = findField.getType();
|
||||||
|
fieldWrapper.mappingType = getFieldMappingType(findField);
|
||||||
|
|
||||||
|
Method setter = ClassUtil.getFirstMethod(clazz, method ->
|
||||||
|
method.getParameterCount() == 1
|
||||||
|
&& Modifier.isPublic(method.getModifiers())
|
||||||
|
&& method.getName().equals("set" + StringUtil.firstCharToUpperCase(fieldName)));
|
||||||
|
fieldWrapper.method = setter;
|
||||||
|
|
||||||
|
wrapperMap.put(fieldName, fieldWrapper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fieldWrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Class<?> getFieldMappingType(Field field) {
|
||||||
|
Class<?> fieldType = field.getType();
|
||||||
|
if (Collection.class.isAssignableFrom(fieldType)) {
|
||||||
|
Type genericType = field.getGenericType();
|
||||||
|
if (genericType instanceof ParameterizedType) {
|
||||||
|
Type actualTypeArgument = ((ParameterizedType) genericType).getActualTypeArguments()[0];
|
||||||
|
return (Class<?>) actualTypeArgument;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fieldType.isArray()) {
|
||||||
|
return field.getType().getComponentType();
|
||||||
|
}
|
||||||
|
|
||||||
|
return fieldType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void set(Object value, Object to) {
|
||||||
|
try {
|
||||||
|
method.invoke(to, value);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<?> getFieldType() {
|
||||||
|
return fieldType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<?> getMappingType() {
|
||||||
|
return mappingType;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -71,15 +71,14 @@ public class EntityTestStarter {
|
|||||||
RowUtil.printPretty(rowList);
|
RowUtil.printPretty(rowList);
|
||||||
|
|
||||||
|
|
||||||
// List<Account> accounts1 = accountMapper.selectListByQuery(QueryWrapper.create()
|
List<Account> accounts1 = accountMapper.selectListByQuery(QueryWrapper.create()
|
||||||
// , accountFieldQueryBuilder -> accountFieldQueryBuilder
|
, accountFieldQueryBuilder -> accountFieldQueryBuilder
|
||||||
// .field(Account::getArticles)
|
.field(Account::getArticles)
|
||||||
// .type(Article.class)
|
.queryWrapper(entity ->
|
||||||
// .queryWrapper(entity ->
|
select().from(ARTICLE).where(ARTICLE.ACCOUNT_ID.eq(entity.getId()))
|
||||||
// select().from(ARTICLE).where(ARTICLE.ACCOUNT_ID.eq(entity.getId()))
|
)
|
||||||
// )
|
);
|
||||||
// );
|
System.out.println(accounts1);
|
||||||
// System.out.println(accounts1);
|
|
||||||
|
|
||||||
// MyAccountMapper myAccountMapper = bootstrap.getMapper(MyAccountMapper.class);
|
// MyAccountMapper myAccountMapper = bootstrap.getMapper(MyAccountMapper.class);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user