优化 BaseMapper.selectListByQueryAs() 方法

This commit is contained in:
开源海哥 2023-05-28 09:19:48 +08:00
parent 0f9db633e2
commit e12d92f17c
5 changed files with 70 additions and 120 deletions

View File

@ -358,13 +358,8 @@ public interface BaseMapper<T> {
* @return 数据内容
*/
default <R> R selectOneByQueryAs(QueryWrapper queryWrapper, Class<R> asType) {
try {
MappedStatementTypes.setCurrentType(asType);
List<R> entities = selectListByQueryAs(queryWrapper.limit(1), asType);
return (entities == null || entities.isEmpty()) ? null : entities.get(0);
} finally {
MappedStatementTypes.clear();
}
List<R> entities = selectListByQueryAs(queryWrapper.limit(1), asType);
return (entities == null || entities.isEmpty()) ? null : entities.get(0);
}
/**
@ -434,7 +429,7 @@ public interface BaseMapper<T> {
List<T> selectListByQuery(@Param(FlexConsts.QUERY) QueryWrapper queryWrapper);
default List<T> selectListByQuery(@Param(FlexConsts.QUERY) QueryWrapper queryWrapper
default List<T> selectListByQuery(QueryWrapper queryWrapper
, Consumer<FieldQueryBuilder<T>>... consumers) {
List<T> list = selectListByQuery(queryWrapper);
@ -442,41 +437,7 @@ public interface BaseMapper<T> {
return Collections.emptyList();
}
list.forEach(entity -> {
for (Consumer<FieldQueryBuilder<T>> consumer : consumers) {
FieldQueryBuilder<T> fieldQueryBuilder = new FieldQueryBuilder<>(entity);
consumer.accept(fieldQueryBuilder);
FieldQuery fieldQuery = fieldQueryBuilder.build();
QueryWrapper childQuery = fieldQuery.getQueryWrapper();
FieldWrapper fieldWrapper = FieldWrapper.of(entity.getClass(), fieldQuery.getField());
if (fieldWrapper == null) {
throw new IllegalStateException("Can not find field \"" + fieldQuery.getField() + "\" in class: " + entity.getClass());
}
Class<?> fieldType = fieldWrapper.getFieldType();
Class<?> mappingType = fieldWrapper.getMappingType();
Object value;
try {
MappedStatementTypes.setCurrentType(mappingType);
if (fieldType.isAssignableFrom(List.class)) {
value = selectListByQueryAs(childQuery, mappingType);
} else if (fieldType.isAssignableFrom(Set.class)) {
value = selectListByQueryAs(childQuery, mappingType);
value = new HashSet<>((Collection<?>) value);
} else if (fieldType.isArray()) {
value = selectListByQueryAs(childQuery, mappingType);
value = ((List<?>) value).toArray();
} else {
value = selectOneByQueryAs(childQuery, mappingType);
}
} finally {
MappedStatementTypes.clear();
}
fieldWrapper.set(value, entity);
}
});
__queryFields(list, consumers);
return list;
}
@ -490,62 +451,25 @@ public interface BaseMapper<T> {
* @param asType 接收数据类型
* @return 数据列表
*/
@SelectProvider(type = EntitySqlProvider.class, method = "selectListByQuery")
<R> List<R> selectListByQueryAs(@Param(FlexConsts.QUERY) QueryWrapper queryWrapper, Class<R> asType);
default <R> List<R> selectListByQueryAs(@Param(FlexConsts.QUERY) QueryWrapper queryWrapper, Class<R> asType
, Consumer<FieldQueryBuilder<R>>... consumers) {
List<R> list;
default <R> List<R> selectListByQueryAs(QueryWrapper queryWrapper, Class<R> asType) {
try {
MappedStatementTypes.setCurrentType(asType);
list = selectListByQueryAs(queryWrapper, asType);
return (List<R>) selectListByQuery(queryWrapper);
} finally {
MappedStatementTypes.clear();
}
}
default <R> List<R> selectListByQueryAs(QueryWrapper queryWrapper, Class<R> asType
, Consumer<FieldQueryBuilder<R>>... consumers) {
List<R> list = selectListByQueryAs(queryWrapper, asType);
if (list == null || list.isEmpty()) {
return Collections.emptyList();
} else {
__queryFields(list, consumers);
return list;
}
list.forEach(entity -> {
for (Consumer<FieldQueryBuilder<R>> consumer : consumers) {
FieldQueryBuilder<R> fieldQueryBuilder = new FieldQueryBuilder<>(entity);
consumer.accept(fieldQueryBuilder);
FieldQuery fieldQuery = fieldQueryBuilder.build();
QueryWrapper childQuery = fieldQuery.getQueryWrapper();
FieldWrapper fieldWrapper = FieldWrapper.of(entity.getClass(), fieldQuery.getField());
if (fieldWrapper == null) {
throw new IllegalStateException("Can not find field \"" + fieldQuery.getField() + "\" in class: " + entity.getClass());
}
Class<?> fieldType = fieldWrapper.getFieldType();
Class<?> mappingType = fieldWrapper.getMappingType();
Object value;
try {
MappedStatementTypes.setCurrentType(mappingType);
if (fieldType.isAssignableFrom(List.class)) {
value = selectListByQueryAs(childQuery, mappingType);
} else if (fieldType.isAssignableFrom(Set.class)) {
value = selectListByQueryAs(childQuery, mappingType);
value = new HashSet<>((Collection<?>) value);
} else if (fieldType.isArray()) {
value = selectListByQueryAs(childQuery, mappingType);
value = ((List<?>) value).toArray();
} else {
value = selectOneByQueryAs(childQuery, mappingType);
}
} finally {
MappedStatementTypes.clear();
}
fieldWrapper.set(value, entity);
}
});
return list;
}
@ -786,19 +710,48 @@ public interface BaseMapper<T> {
queryWrapper.limit(offset, page.getPageSize());
if (asType != null) {
try {
// 调用内部方法不走代理需要主动设置 MappedStatementType
// fixed https://gitee.com/mybatis-flex/mybatis-flex/issues/I73BP6
MappedStatementTypes.setCurrentType(asType);
List<R> records = selectListByQueryAs(queryWrapper, asType, consumers);
page.setRecords(records);
} finally {
MappedStatementTypes.clear();
}
List<R> records = selectListByQueryAs(queryWrapper, asType);
__queryFields(records, consumers);
page.setRecords(records);
} else {
List<R> records = (List<R>) selectListByQuery(queryWrapper);
__queryFields(records, consumers);
page.setRecords(records);
}
return page;
}
default <R> void __queryFields(List<R> list, Consumer<FieldQueryBuilder<R>>[] consumers) {
if (CollectionUtil.isEmpty(list) || ArrayUtil.isEmpty(consumers) || consumers[0] == null) {
return;
}
list.forEach(entity -> {
for (Consumer<FieldQueryBuilder<R>> consumer : consumers) {
FieldQueryBuilder<R> fieldQueryBuilder = new FieldQueryBuilder<>(entity);
consumer.accept(fieldQueryBuilder);
FieldQuery fieldQuery = fieldQueryBuilder.build();
QueryWrapper childQuery = fieldQuery.getQueryWrapper();
FieldWrapper fieldWrapper = FieldWrapper.of(entity.getClass(), fieldQuery.getField());
Class<?> fieldType = fieldWrapper.getFieldType();
Class<?> mappingType = fieldWrapper.getMappingType();
Object value;
if (fieldType.isAssignableFrom(List.class)) {
value = selectListByQueryAs(childQuery, mappingType);
} else if (fieldType.isAssignableFrom(Set.class)) {
value = selectListByQueryAs(childQuery, mappingType);
value = new HashSet<>((Collection<?>) value);
} else if (fieldType.isArray()) {
value = selectListByQueryAs(childQuery, mappingType);
value = ((List<?>) value).toArray();
} else {
value = selectOneByQueryAs(childQuery, mappingType);
}
fieldWrapper.set(value, entity);
}
});
}
}

View File

@ -41,7 +41,6 @@ public class FlexConsts {
public static final String IGNORE_NULLS = "$$ignoreNulls";
public static final String METHOD_INSERT_BATCH = "insertBatch";
public static final String METHOD_SELECT_LIST_BY_QUERY_AS = "selectListByQueryAs";
/**
* entity 使用逻辑删除时0 entity 的正常状态

View File

@ -133,9 +133,9 @@ public class FlexConfiguration extends Configuration {
public MappedStatement getMappedStatement(String id) {
MappedStatement ms = super.getMappedStatement(id);
//动态 resultsMap
if (id.endsWith(FlexConsts.METHOD_SELECT_LIST_BY_QUERY_AS)) {
Class<?> asType = MappedStatementTypes.getCurrentType();
//动态 resultsMap方法名称为selectListByQuery
Class<?> asType = MappedStatementTypes.getCurrentType();
if (asType != null) {
return MapUtil.computeIfAbsent(dynamicMappedStatementCache, asType,
aClass -> replaceResultMap(ms, TableInfoFactory.ofEntityClass(asType))
);

View File

@ -16,7 +16,6 @@
package com.mybatisflex.core.mybatis;
import com.mybatisflex.annotation.UseDataSource;
import com.mybatisflex.core.FlexConsts;
import com.mybatisflex.core.FlexGlobalConfig;
import com.mybatisflex.core.datasource.DataSourceKey;
import com.mybatisflex.core.datasource.FlexDataSource;
@ -46,11 +45,7 @@ public class MapperInvocationHandler implements InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
boolean clearDsKey = false;
boolean clearDbType = false;
boolean isSelectListByQueryAsMethod = FlexConsts.METHOD_SELECT_LIST_BY_QUERY_AS.equals(method.getName());
try {
if (isSelectListByQueryAsMethod){
MappedStatementTypes.setCurrentType((Class<?>) args[1]);
}
//获取用户动态指定由用户指定数据源则应该有用户清除
String dataSourceKey = DataSourceKey.get();
@ -78,9 +73,6 @@ public class MapperInvocationHandler implements InvocationHandler {
}
return method.invoke(mapper, args);
} finally {
if (isSelectListByQueryAsMethod){
MappedStatementTypes.clear();
}
if (clearDbType) {
DialectFactory.clearHintDbType();
}

View File

@ -15,6 +15,8 @@
*/
package com.mybatisflex.core.util;
import com.mybatisflex.core.exception.FlexExceptions;
import java.lang.reflect.*;
import java.util.Collection;
import java.util.Map;
@ -26,7 +28,7 @@ public class FieldWrapper {
private Class<?> fieldType;
private Class<?> mappingType;
private Method method;
private Method setterMethod;
public static FieldWrapper of(Class<?> clazz, String fieldName) {
Map<String, FieldWrapper> wrapperMap = cache.get(clazz);
@ -46,18 +48,22 @@ public class FieldWrapper {
if (fieldWrapper == null) {
Field findField = ClassUtil.getFirstField(clazz, field -> field.getName().equals(fieldName));
if (findField == null) {
return null;
throw new IllegalStateException("Can not find field \"" + fieldName + "\" in class: " + clazz);
}
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;
if (setter == null) {
throw FlexExceptions.wrap("Can not find method \"set" + StringUtil.firstCharToUpperCase(fieldName) + "\" in class: " + clazz);
}
fieldWrapper = new FieldWrapper();
fieldWrapper.fieldType = findField.getType();
fieldWrapper.mappingType = parseMappingType(findField);
fieldWrapper.setterMethod = setter;
wrapperMap.put(fieldName, fieldWrapper);
}
@ -67,7 +73,7 @@ public class FieldWrapper {
return fieldWrapper;
}
private static Class<?> getFieldMappingType(Field field) {
private static Class<?> parseMappingType(Field field) {
Class<?> fieldType = field.getType();
if (Collection.class.isAssignableFrom(fieldType)) {
Type genericType = field.getGenericType();
@ -87,7 +93,7 @@ public class FieldWrapper {
public void set(Object value, Object to) {
try {
method.invoke(to, value);
setterMethod.invoke(to, value);
} catch (Exception e) {
throw new RuntimeException(e);
}