mirror of
https://gitee.com/mybatis-flex/mybatis-flex.git
synced 2025-12-07 00:58:24 +08:00
commit
75a1df800e
@ -15,29 +15,119 @@
|
||||
*/
|
||||
package com.mybatisflex.core.field;
|
||||
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 查询属性的信息。
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public class FieldQuery implements Serializable {
|
||||
|
||||
private String field;
|
||||
private QueryWrapper queryWrapper;
|
||||
private String className;
|
||||
private String fieldName;
|
||||
private FieldType fieldType = FieldType.AUTO;
|
||||
private boolean prevent;
|
||||
private QueryBuilder queryBuilder;
|
||||
|
||||
public String getField() {
|
||||
return field;
|
||||
public String getClassName() {
|
||||
return className;
|
||||
}
|
||||
|
||||
public void setField(String field) {
|
||||
this.field = field;
|
||||
public void setClassName(String className) {
|
||||
this.className = className;
|
||||
}
|
||||
|
||||
public QueryWrapper getQueryWrapper() {
|
||||
return queryWrapper;
|
||||
public String getFieldName() {
|
||||
return fieldName;
|
||||
}
|
||||
|
||||
public void setQueryWrapper(QueryWrapper queryWrapper) {
|
||||
this.queryWrapper = queryWrapper;
|
||||
public void setFieldName(String fieldName) {
|
||||
this.fieldName = fieldName;
|
||||
}
|
||||
|
||||
public FieldType getFieldType() {
|
||||
return fieldType;
|
||||
}
|
||||
|
||||
public void setFieldType(FieldType fieldType) {
|
||||
this.fieldType = fieldType;
|
||||
}
|
||||
|
||||
public boolean isPrevent() {
|
||||
return prevent;
|
||||
}
|
||||
|
||||
public void setPrevent(boolean prevent) {
|
||||
this.prevent = prevent;
|
||||
}
|
||||
|
||||
public QueryBuilder getQueryBuilder() {
|
||||
return queryBuilder;
|
||||
}
|
||||
|
||||
public void setQueryBuilder(QueryBuilder queryBuilder) {
|
||||
this.queryBuilder = queryBuilder;
|
||||
}
|
||||
|
||||
public static class Builder<T> {
|
||||
|
||||
private final FieldQuery fieldQuery;
|
||||
|
||||
public Builder(String className, String fieldName) {
|
||||
this.fieldQuery = new FieldQuery();
|
||||
this.fieldQuery.setClassName(className);
|
||||
this.fieldQuery.setFieldName(fieldName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置属性类型(可选,默认自动识别)。
|
||||
*
|
||||
* @param fieldType 属性类型
|
||||
* @return 构建者
|
||||
*/
|
||||
public Builder<T> fieldType(FieldType fieldType) {
|
||||
this.fieldQuery.setFieldType(fieldType);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 阻止对嵌套类属性的查询,只对 {@link FieldType#COLLECTION} 与
|
||||
* {@link FieldType#ENTITY} 两种属性类型有效。
|
||||
*
|
||||
* @return 构建者
|
||||
*/
|
||||
public Builder<T> prevent() {
|
||||
this.fieldQuery.setPrevent(true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置是否阻止对嵌套类属性的查询,只对 {@link FieldType#COLLECTION} 与
|
||||
* {@link FieldType#ENTITY} 两种属性类型有效。
|
||||
*
|
||||
* @param prevent 是否阻止对嵌套类属性查询
|
||||
* @return 构建者
|
||||
*/
|
||||
public Builder<T> prevent(boolean prevent) {
|
||||
this.fieldQuery.setPrevent(prevent);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置查询这个属性的 {@code QueryWrapper} 对象。
|
||||
*
|
||||
* @param queryBuilder 查询包装器
|
||||
* @return 构建者
|
||||
*/
|
||||
public Builder<T> queryWrapper(QueryBuilder<T> queryBuilder) {
|
||||
this.fieldQuery.setQueryBuilder(queryBuilder);
|
||||
return this;
|
||||
}
|
||||
|
||||
protected FieldQuery build() {
|
||||
return this.fieldQuery;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -15,36 +15,60 @@
|
||||
*/
|
||||
package com.mybatisflex.core.field;
|
||||
|
||||
import com.mybatisflex.core.exception.FlexAssert;
|
||||
import com.mybatisflex.core.util.LambdaGetter;
|
||||
import com.mybatisflex.core.util.LambdaUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 属性查询构建者。
|
||||
*
|
||||
* @param <T> 属性所在实体类类型
|
||||
* @author 开源海哥
|
||||
* @author 王帅
|
||||
*/
|
||||
public class FieldQueryBuilder<T> implements Serializable {
|
||||
|
||||
private T entity;
|
||||
private FieldQuery fieldQuery = new FieldQuery();
|
||||
private FieldQuery.Builder<?> builder;
|
||||
|
||||
public FieldQueryBuilder(T entity) {
|
||||
this.entity = entity;
|
||||
/**
|
||||
* 为指定属性创建查询。
|
||||
*
|
||||
* @param fn Lambda 引用
|
||||
* @return {@link FieldQuery.Builder} 构建者
|
||||
*/
|
||||
public FieldQuery.Builder<T> field(LambdaGetter<T> fn) {
|
||||
return createBuilder(fn);
|
||||
}
|
||||
|
||||
public FieldQueryBuilder<T> field(String field) {
|
||||
fieldQuery.setField(field);
|
||||
return this;
|
||||
/**
|
||||
* 为指定嵌套属性创建查询。
|
||||
*
|
||||
* @param <N> 嵌套属性类型
|
||||
* @param fn Lambda 引用
|
||||
* @return {@link FieldQuery.Builder} 构建者
|
||||
*/
|
||||
public <N> FieldQuery.Builder<N> nestedField(LambdaGetter<N> fn) {
|
||||
return createBuilder(fn);
|
||||
}
|
||||
|
||||
public FieldQueryBuilder<T> field(LambdaGetter<T> fn) {
|
||||
return field(LambdaUtil.getFieldName(fn));
|
||||
}
|
||||
|
||||
public FieldQueryBuilder<T> queryWrapper(QueryBuilder<T> fun) {
|
||||
fieldQuery.setQueryWrapper(fun.build(entity));
|
||||
return this;
|
||||
/**
|
||||
* <p>创建 {@link FieldQuery.Builder} 用于构建属性类型与 {@code QueryWrapper} 用于查询。
|
||||
*
|
||||
* <p>该方法主要用作于创建构建者对象,以及泛型的转换。
|
||||
*/
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
private <R> FieldQuery.Builder<R> createBuilder(LambdaGetter fn) {
|
||||
FlexAssert.notNull(fn, "Field can not be null.");
|
||||
String className = LambdaUtil.getClassName(fn);
|
||||
String fieldName = LambdaUtil.getFieldName(fn);
|
||||
builder = new FieldQuery.Builder<>(className, fieldName);
|
||||
return (FieldQuery.Builder<R>) builder;
|
||||
}
|
||||
|
||||
public FieldQuery build() {
|
||||
return fieldQuery;
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* 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.field;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.mybatisflex.core.exception.FlexExceptions;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import com.mybatisflex.core.row.Row;
|
||||
import com.mybatisflex.core.util.ClassUtil;
|
||||
import com.mybatisflex.core.util.CollectionUtil;
|
||||
import com.mybatisflex.core.util.FieldWrapper;
|
||||
import org.apache.ibatis.reflection.TypeParameterResolver;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 属性查询管理。
|
||||
*
|
||||
* @author 王帅
|
||||
* @since 2023-07-15
|
||||
*/
|
||||
public class FieldQueryManager {
|
||||
|
||||
private FieldQueryManager() {
|
||||
}
|
||||
|
||||
public static void queryFields(BaseMapper<?> mapper, Collection<?> entities, Map<String, FieldQuery> fieldQueryMap) {
|
||||
for (Object entity : entities) {
|
||||
Class<?> entityClass = entity.getClass();
|
||||
List<Field> allFields = ClassUtil.getAllFields(entityClass);
|
||||
for (Field field : allFields) {
|
||||
String mapKey = entityClass.getName() + '#' + field.getName();
|
||||
FieldQuery fieldQuery = fieldQueryMap.get(mapKey);
|
||||
// 属性包含对应的查询包装器
|
||||
if (fieldQuery != null) {
|
||||
@SuppressWarnings("unchecked")
|
||||
QueryWrapper queryWrapper = fieldQuery.getQueryBuilder().build(entity);
|
||||
FieldType fieldType = fieldQuery.getFieldType();
|
||||
if (fieldType == FieldType.AUTO) {
|
||||
fieldType = FieldType.determineFieldType(field);
|
||||
}
|
||||
Class<?> realFieldType = field.getType();
|
||||
Object value;
|
||||
switch (fieldType) {
|
||||
case COLLECTION:
|
||||
Class<?> genericType = getGenericType(entityClass, field);
|
||||
List<?> list = mapper.selectListByQueryAs(queryWrapper, genericType);
|
||||
// 转换成 Collection 子类,或者空 Collection 对象,避免 NPE
|
||||
if (list != null) {
|
||||
value = getCollectionValue(realFieldType, list);
|
||||
// 循环查询泛型实体类
|
||||
if ((!Number.class.isAssignableFrom(genericType)
|
||||
|| !String.class.isAssignableFrom(genericType)
|
||||
|| !Map.class.isAssignableFrom(genericType))
|
||||
&& !fieldQuery.isPrevent()) {
|
||||
queryFields(mapper, (Collection<?>) value, fieldQueryMap);
|
||||
}
|
||||
} else {
|
||||
value = new ArrayList<>();
|
||||
}
|
||||
break;
|
||||
case ENTITY:
|
||||
value = mapper.selectOneByQueryAs(queryWrapper, realFieldType);
|
||||
// 循环查询嵌套类
|
||||
if (!fieldQuery.isPrevent()) {
|
||||
queryFields(mapper, Collections.singletonList(value), fieldQueryMap);
|
||||
}
|
||||
break;
|
||||
case MAP:
|
||||
List<Row> rows = mapper.selectRowsByQuery(queryWrapper);
|
||||
// 转换成 Map 子类,或者空 Map 对象,避免 NPE
|
||||
if (rows != null && !rows.isEmpty() && rows.get(0) != null) {
|
||||
value = getMapValue(realFieldType, rows.get(0));
|
||||
} else {
|
||||
value = new HashMap<>();
|
||||
}
|
||||
break;
|
||||
case BASIC:
|
||||
value = mapper.selectObjectByQueryAs(queryWrapper, realFieldType);
|
||||
break;
|
||||
case ARRAY:
|
||||
Class<?> componentType = realFieldType.getComponentType();
|
||||
List<?> objects = mapper.selectListByQueryAs(queryWrapper, componentType);
|
||||
value = getArrayValue(componentType, objects);
|
||||
break;
|
||||
default:
|
||||
value = null;
|
||||
break;
|
||||
}
|
||||
// 属性查询出来的值不为 null 时,为属性设置值
|
||||
if (value != null) {
|
||||
FieldWrapper.of(entityClass, fieldQuery.getFieldName()).set(value, entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Class<?> getGenericType(Class<?> entityClass, Field field) {
|
||||
Type genericType = TypeParameterResolver.resolveFieldType(field, entityClass);
|
||||
if (genericType instanceof ParameterizedType) {
|
||||
return (Class<?>) ((ParameterizedType) genericType).getActualTypeArguments()[0];
|
||||
} else {
|
||||
throw FlexExceptions.wrap("Can not resolve generic type %s in field %s", genericType, field.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
private static Object getCollectionValue(Class<?> fieldType, Collection value) {
|
||||
if (ClassUtil.canInstance(fieldType.getModifiers())) {
|
||||
Collection collection = (Collection) ClassUtil.newInstance(fieldType);
|
||||
collection.addAll(value);
|
||||
return collection;
|
||||
}
|
||||
|
||||
if (List.class.isAssignableFrom(fieldType)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (Set.class.isAssignableFrom(fieldType)) {
|
||||
return new HashSet<>(value);
|
||||
}
|
||||
|
||||
throw FlexExceptions.wrap("Unsupported collection type.");
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
private static Object getMapValue(Class<?> fieldType, Map value) {
|
||||
if (ClassUtil.canInstance(fieldType.getModifiers())) {
|
||||
Map map = (Map) ClassUtil.newInstance(fieldType);
|
||||
map.putAll(value);
|
||||
return map;
|
||||
}
|
||||
|
||||
return new HashMap<>(value);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T> Object getArrayValue(Class<?> componentType, List<T> list) {
|
||||
if (CollectionUtil.isEmpty(list)) {
|
||||
return Array.newInstance(componentType, 0);
|
||||
}
|
||||
|
||||
T[] array = (T[]) Array.newInstance(componentType, list.size());
|
||||
|
||||
for (int rows = 0; rows < list.size(); rows++) {
|
||||
array[rows] = list.get(rows);
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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.field;
|
||||
|
||||
import com.mybatisflex.core.util.CollectionUtil;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.*;
|
||||
import java.time.chrono.JapaneseDate;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 属性类型。
|
||||
*
|
||||
* @author 王帅
|
||||
* @since 2023-07-15
|
||||
*/
|
||||
public enum FieldType {
|
||||
|
||||
/**
|
||||
* Map 对象。
|
||||
*/
|
||||
MAP,
|
||||
|
||||
/**
|
||||
* 自动推断。
|
||||
*/
|
||||
AUTO,
|
||||
|
||||
/**
|
||||
* 数组。
|
||||
*/
|
||||
ARRAY,
|
||||
|
||||
/**
|
||||
* 基本数据类型。
|
||||
*/
|
||||
BASIC,
|
||||
|
||||
/**
|
||||
* 实体类。
|
||||
*/
|
||||
ENTITY,
|
||||
|
||||
/**
|
||||
* 集合。
|
||||
*/
|
||||
COLLECTION;
|
||||
|
||||
private static final Set<Class<?>> BASIC_TYPES = CollectionUtil.newHashSet(
|
||||
int.class, Integer.class,
|
||||
short.class, Short.class,
|
||||
long.class, Long.class,
|
||||
float.class, Float.class,
|
||||
double.class, Double.class,
|
||||
boolean.class, Boolean.class,
|
||||
Date.class, java.sql.Date.class, Time.class, Timestamp.class,
|
||||
Instant.class, LocalDate.class, LocalDateTime.class, LocalTime.class, OffsetDateTime.class, OffsetTime.class, ZonedDateTime.class,
|
||||
Year.class, Month.class, YearMonth.class, JapaneseDate.class,
|
||||
byte[].class, Byte[].class, Byte.class,
|
||||
BigInteger.class, BigDecimal.class,
|
||||
char.class, String.class, Character.class
|
||||
);
|
||||
|
||||
/**
|
||||
* 自动推断属性类型。
|
||||
*
|
||||
* @param field 属性
|
||||
* @return 属性类型
|
||||
* @see FieldType#AUTO
|
||||
*/
|
||||
public static FieldType determineFieldType(Field field) {
|
||||
Class<?> fieldType = field.getType();
|
||||
if (Collection.class.isAssignableFrom(fieldType)) {
|
||||
return COLLECTION;
|
||||
} else if (Map.class.isAssignableFrom(fieldType)) {
|
||||
return MAP;
|
||||
} else if (fieldType.isArray()) {
|
||||
return ARRAY;
|
||||
} else if (BASIC_TYPES.contains(fieldType)
|
||||
|| fieldType.isEnum()) {
|
||||
return BASIC;
|
||||
} else {
|
||||
return ENTITY;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -17,8 +17,19 @@ package com.mybatisflex.core.field;
|
||||
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
|
||||
/**
|
||||
* 属性查询条件构建。
|
||||
*
|
||||
* @param <T> 实体类类型
|
||||
*/
|
||||
public interface QueryBuilder<T> {
|
||||
|
||||
/**
|
||||
* 构建查询属性的 {@link QueryWrapper} 对象。
|
||||
*
|
||||
* @param entity 实体类
|
||||
* @return 查询条件
|
||||
*/
|
||||
QueryWrapper build(T entity);
|
||||
|
||||
}
|
||||
|
||||
@ -42,6 +42,12 @@ public class LambdaUtil {
|
||||
return PropertyNamer.methodToProperty(methodName);
|
||||
}
|
||||
|
||||
public static <T> String getClassName(LambdaGetter<T> getter) {
|
||||
SerializedLambda lambda = getSerializedLambda(getter);
|
||||
String className = lambda.getImplClass();
|
||||
return className.replace('/', '.');
|
||||
}
|
||||
|
||||
|
||||
public static <T> String getAliasName(LambdaGetter<T> getter, boolean withPrefix) {
|
||||
QueryColumn queryColumn = getQueryColumn(getter);
|
||||
|
||||
@ -20,6 +20,7 @@ import com.mybatisflex.core.constant.SqlConsts;
|
||||
import com.mybatisflex.core.exception.FlexExceptions;
|
||||
import com.mybatisflex.core.field.FieldQuery;
|
||||
import com.mybatisflex.core.field.FieldQueryBuilder;
|
||||
import com.mybatisflex.core.field.FieldQueryManager;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.core.query.*;
|
||||
import com.mybatisflex.core.relation.RelationManager;
|
||||
@ -176,41 +177,23 @@ public class MapperUtil {
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public static <R> void queryFields(BaseMapper<?> mapper, 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());
|
||||
Map<String, FieldQuery> fieldQueryMap = new HashMap<>();
|
||||
for (Consumer<FieldQueryBuilder<R>> consumer : consumers) {
|
||||
FieldQueryBuilder<R> fieldQueryBuilder = new FieldQueryBuilder<>();
|
||||
consumer.accept(fieldQueryBuilder);
|
||||
FieldQuery fieldQuery = fieldQueryBuilder.build();
|
||||
String className = fieldQuery.getClassName();
|
||||
String fieldName = fieldQuery.getFieldName();
|
||||
String mapKey = className + '#' + fieldName;
|
||||
fieldQueryMap.put(mapKey, fieldQuery);
|
||||
}
|
||||
|
||||
Class<?> fieldType = fieldWrapper.getFieldType();
|
||||
Class<?> mappingType = fieldWrapper.getMappingType();
|
||||
|
||||
Object value;
|
||||
if (Collection.class.isAssignableFrom(fieldType)) {
|
||||
value = mapper.selectListByQueryAs(childQuery, mappingType);
|
||||
if (!fieldType.isAssignableFrom(value.getClass())) {
|
||||
fieldType = getCollectionWrapType(fieldType);
|
||||
Collection newValue = (Collection) ClassUtil.newInstance(fieldType);
|
||||
newValue.addAll((Collection) value);
|
||||
value = newValue;
|
||||
}
|
||||
} else if (fieldType.isArray()) {
|
||||
value = mapper.selectListByQueryAs(childQuery, mappingType);
|
||||
value = ((List<?>) value).toArray();
|
||||
} else {
|
||||
value = mapper.selectOneByQueryAs(childQuery, mappingType);
|
||||
}
|
||||
fieldWrapper.set(value, entity);
|
||||
}
|
||||
});
|
||||
FieldQueryManager.queryFields(mapper, list, fieldQueryMap);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -117,7 +117,8 @@ public class AccountTester {
|
||||
Account account = new Account();
|
||||
account.setId(4L);
|
||||
account.setUserName("test04");
|
||||
accountMapper.insertSelectiveWithPk(account);
|
||||
int rows = accountMapper.insertSelectiveWithPk(account);
|
||||
System.out.println(rows);
|
||||
|
||||
accounts = accountMapper.selectAll();
|
||||
System.out.println(accounts);
|
||||
|
||||
@ -16,11 +16,9 @@
|
||||
|
||||
package com.mybatisflex.test.model;
|
||||
|
||||
import com.mybatisflex.annotation.Column;
|
||||
import com.mybatisflex.annotation.RelationManyToMany;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 用户信息。
|
||||
@ -33,7 +31,6 @@ public class UserInfo {
|
||||
private Integer userId;
|
||||
private String userName;
|
||||
private String password;
|
||||
@Column(ignore = true)
|
||||
private String idNumber;
|
||||
|
||||
@RelationManyToMany(
|
||||
@ -115,44 +112,4 @@ public class UserInfo {
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
UserInfo userInfo = (UserInfo) o;
|
||||
|
||||
if (!Objects.equals(userId, userInfo.userId)) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(userName, userInfo.userName)) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(password, userInfo.password)) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(idNumber, userInfo.idNumber)) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(roleList, userInfo.roleList)) {
|
||||
return false;
|
||||
}
|
||||
return Objects.equals(orderInfoList, userInfo.orderInfoList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = userId != null ? userId.hashCode() : 0;
|
||||
result = 31 * result + (userName != null ? userName.hashCode() : 0);
|
||||
result = 31 * result + (password != null ? password.hashCode() : 0);
|
||||
result = 31 * result + (idNumber != null ? idNumber.hashCode() : 0);
|
||||
result = 31 * result + (roleList != null ? roleList.hashCode() : 0);
|
||||
result = 31 * result + (orderInfoList != null ? orderInfoList.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -16,8 +16,8 @@
|
||||
|
||||
package com.mybatisflex.test.model;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.TreeSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 用户 VO 对象。
|
||||
@ -30,7 +30,9 @@ public class UserVO {
|
||||
|
||||
private String userId;
|
||||
private String userName;
|
||||
private TreeSet<Role> roleList;
|
||||
// private TreeSet<Role> roleList;
|
||||
// private Role[] roleList;
|
||||
private HashMap<String, Object> roleList;
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
@ -48,11 +50,11 @@ public class UserVO {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public Collection<Role> getRoleList() {
|
||||
public Map<String, Object> getRoleList() {
|
||||
return roleList;
|
||||
}
|
||||
|
||||
public void setRoleList(TreeSet<Role> roleList) {
|
||||
public void setRoleList(HashMap<String, Object> roleList) {
|
||||
this.roleList = roleList;
|
||||
}
|
||||
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
|
||||
package com.mybatisflex.test.mapper;
|
||||
|
||||
import com.mybatisflex.core.field.FieldType;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import com.mybatisflex.test.model.*;
|
||||
@ -73,6 +74,7 @@ class UserMapperTest {
|
||||
List<UserVO> userVOs = userMapper.selectListByQueryAs(queryWrapper, UserVO.class,
|
||||
fieldQueryBuilder -> fieldQueryBuilder
|
||||
.field(UserVO::getRoleList)
|
||||
.prevent(true)
|
||||
.queryWrapper(user -> QueryWrapper.create()
|
||||
.select()
|
||||
.from(ROLE)
|
||||
@ -136,6 +138,40 @@ class UserMapperTest {
|
||||
userInfos.forEach(System.err::println);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testComplexSelectListFields() {
|
||||
List<UserInfo> userInfos = userMapper.selectListByQueryAs(QueryWrapper.create(), UserInfo.class,
|
||||
c -> c.field(UserInfo::getIdNumber).fieldType(FieldType.BASIC).queryWrapper(userInfo ->
|
||||
QueryWrapper.create()
|
||||
.select(ID_CARD.ID_NUMBER)
|
||||
.from(ID_CARD)
|
||||
.where(ID_CARD.ID.eq(userInfo.getUserId()))
|
||||
),
|
||||
c -> c.field(UserInfo::getRoleList).prevent().queryWrapper(userInfo ->
|
||||
QueryWrapper.create()
|
||||
.select()
|
||||
.from(ROLE.as("r"))
|
||||
.leftJoin(USER_ROLE).as("ur").on(USER_ROLE.ROLE_ID.eq(ROLE.ROLE_ID))
|
||||
.where(USER_ROLE.USER_ID.eq(userInfo.getUserId()))
|
||||
),
|
||||
c -> c.field(UserInfo::getOrderInfoList).queryWrapper(userInfo ->
|
||||
QueryWrapper.create()
|
||||
.select()
|
||||
.from(ORDER.as("o"))
|
||||
.leftJoin(USER_ORDER).as("uo").on(USER_ORDER.ORDER_ID.eq(ORDER.ORDER_ID))
|
||||
.where(USER_ORDER.USER_ID.eq(userInfo.getUserId()))
|
||||
),
|
||||
c -> c.nestedField(OrderInfo::getGoodList).prevent().queryWrapper(orderInfo ->
|
||||
QueryWrapper.create()
|
||||
.select()
|
||||
.from(GOOD.as("g"))
|
||||
.leftJoin(ORDER_GOOD).as("og").on(ORDER_GOOD.GOOD_ID.eq(GOOD.GOOD_ID))
|
||||
.where(ORDER_GOOD.ORDER_ID.eq(orderInfo.getOrderId()))
|
||||
)
|
||||
);
|
||||
userInfos.forEach(System.err::println);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEquals() {
|
||||
QueryWrapper queryWrapper1 = QueryWrapper.create()
|
||||
@ -150,16 +186,48 @@ class UserMapperTest {
|
||||
.leftJoin(GOOD).as("g").on(GOOD.GOOD_ID.eq(ORDER_GOOD.GOOD_ID))
|
||||
.orderBy(USER.USER_ID.asc(), ROLE.ROLE_ID.asc(), ORDER.ORDER_ID.asc(), GOOD.GOOD_ID.asc());
|
||||
List<UserInfo> userInfos1 = userMapper.selectListByQueryAs(queryWrapper1, UserInfo.class);
|
||||
userInfos1.forEach(System.err::println);
|
||||
|
||||
QueryWrapper queryWrapper2 = QueryWrapper.create()
|
||||
.select(USER.ALL_COLUMNS, ID_CARD.ID_NUMBER)
|
||||
.from(USER.as("u"))
|
||||
.leftJoin(ID_CARD).as("i").on(USER.USER_ID.eq(ID_CARD.ID));
|
||||
List<UserInfo> userInfos2 = userMapper.selectListWithRelationsByQueryAs(queryWrapper2, UserInfo.class);
|
||||
userInfos2.forEach(System.err::println);
|
||||
|
||||
Assertions.assertEquals(userInfos1, userInfos2);
|
||||
List<UserInfo> userInfos3 = userMapper.selectListByQueryAs(QueryWrapper.create(), UserInfo.class,
|
||||
c -> c.field(UserInfo::getIdNumber).fieldType(FieldType.BASIC).queryWrapper(userInfo ->
|
||||
QueryWrapper.create()
|
||||
.select(ID_CARD.ID_NUMBER)
|
||||
.from(ID_CARD)
|
||||
.where(ID_CARD.ID.eq(userInfo.getUserId()))
|
||||
),
|
||||
c -> c.field(UserInfo::getRoleList).prevent().queryWrapper(userInfo ->
|
||||
QueryWrapper.create()
|
||||
.select()
|
||||
.from(ROLE.as("r"))
|
||||
.leftJoin(USER_ROLE).as("ur").on(USER_ROLE.ROLE_ID.eq(ROLE.ROLE_ID))
|
||||
.where(USER_ROLE.USER_ID.eq(userInfo.getUserId()))
|
||||
.orderBy(ROLE.ROLE_ID.asc())
|
||||
),
|
||||
c -> c.field(UserInfo::getOrderInfoList).queryWrapper(userInfo ->
|
||||
QueryWrapper.create()
|
||||
.select()
|
||||
.from(ORDER.as("o"))
|
||||
.leftJoin(USER_ORDER).as("uo").on(USER_ORDER.ORDER_ID.eq(ORDER.ORDER_ID))
|
||||
.where(USER_ORDER.USER_ID.eq(userInfo.getUserId()))
|
||||
.orderBy(ORDER.ORDER_ID.asc())
|
||||
),
|
||||
c -> c.nestedField(OrderInfo::getGoodList).prevent().queryWrapper(orderInfo ->
|
||||
QueryWrapper.create()
|
||||
.select()
|
||||
.from(GOOD.as("g"))
|
||||
.leftJoin(ORDER_GOOD).as("og").on(ORDER_GOOD.GOOD_ID.eq(GOOD.GOOD_ID))
|
||||
.where(ORDER_GOOD.ORDER_ID.eq(orderInfo.getOrderId()))
|
||||
.orderBy(GOOD.GOOD_ID.asc())
|
||||
)
|
||||
);
|
||||
|
||||
Assertions.assertEquals(userInfos1.toString(), userInfos2.toString());
|
||||
Assertions.assertEquals(userInfos1.toString(), userInfos3.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user