From 38207f6b70cd2b873b81227e8de7d0bbcaf00632 Mon Sep 17 00:00:00 2001 From: Suomm <1474983351@qq.com> Date: Sat, 15 Jul 2023 17:46:56 +0800 Subject: [PATCH 1/8] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=20lambda=20=E7=B1=BB=E5=90=8D=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/mybatisflex/core/util/LambdaUtil.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/util/LambdaUtil.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/util/LambdaUtil.java index 75cf1f4d..1083d612 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/util/LambdaUtil.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/util/LambdaUtil.java @@ -42,6 +42,12 @@ public class LambdaUtil { return PropertyNamer.methodToProperty(methodName); } + public static String getClassName(LambdaGetter getter) { + SerializedLambda lambda = getSerializedLambda(getter); + String className = lambda.getImplClass(); + return className.replace('/', '.'); + } + public static String getAliasName(LambdaGetter getter, boolean withPrefix) { QueryColumn queryColumn = getQueryColumn(getter); From 2592ed5f4f167b33f67b41749a27fdeb847be705 Mon Sep 17 00:00:00 2001 From: Suomm <1474983351@qq.com> Date: Sat, 15 Jul 2023 17:47:45 +0800 Subject: [PATCH 2/8] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=20FieldType=20?= =?UTF-8?q?=E7=94=A8=E4=BA=8E=E6=8C=87=E5=AE=9A=E5=B1=9E=E6=80=A7=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E6=97=B6=E5=B1=9E=E6=80=A7=E7=B1=BB=E5=9E=8B=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mybatisflex/core/field/FieldType.java | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 mybatis-flex-core/src/main/java/com/mybatisflex/core/field/FieldType.java diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/field/FieldType.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/field/FieldType.java new file mode 100644 index 00000000..158f635b --- /dev/null +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/field/FieldType.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * 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 + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * 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> 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; + } + } + +} From fbe722316a2b7750e6e1a202231ecd2c6b760b63 Mon Sep 17 00:00:00 2001 From: Suomm <1474983351@qq.com> Date: Sat, 15 Jul 2023 17:49:08 +0800 Subject: [PATCH 3/8] =?UTF-8?q?refactor:=20=E9=80=9A=E8=BF=87=20FieldQuery?= =?UTF-8?q?Builder=20=E6=8C=87=E5=AE=9A=E5=AF=B9=E5=93=AA=E4=B8=AA?= =?UTF-8?q?=E5=B1=9E=E6=80=A7=E8=BF=9B=E8=A1=8C=E6=9F=A5=E8=AF=A2=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/field/FieldQueryBuilder.java | 54 +++++++++++++------ 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/field/FieldQueryBuilder.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/field/FieldQueryBuilder.java index d91b9769..9cbc9296 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/field/FieldQueryBuilder.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/field/FieldQueryBuilder.java @@ -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 属性所在实体类类型 + * @author 开源海哥 + * @author 王帅 + */ public class FieldQueryBuilder 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 field(LambdaGetter fn) { + return createBuilder(fn); } - public FieldQueryBuilder field(String field) { - fieldQuery.setField(field); - return this; + /** + * 为指定嵌套属性创建查询。 + * + * @param 嵌套属性类型 + * @param fn Lambda 引用 + * @return {@link FieldQuery.Builder} 构建者 + */ + public FieldQuery.Builder nestedField(LambdaGetter fn) { + return createBuilder(fn); } - public FieldQueryBuilder field(LambdaGetter fn) { - return field(LambdaUtil.getFieldName(fn)); - } - - public FieldQueryBuilder queryWrapper(QueryBuilder fun) { - fieldQuery.setQueryWrapper(fun.build(entity)); - return this; + /** + *

创建 {@link FieldQuery.Builder} 用于构建属性类型与 {@code QueryWrapper} 用于查询。 + * + *

该方法主要用作于创建构建者对象,以及泛型的转换。 + */ + @SuppressWarnings({"rawtypes", "unchecked"}) + private FieldQuery.Builder 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) builder; } public FieldQuery build() { - return fieldQuery; + return builder.build(); } } From 19644951a0d3c051168349fe96fb154b01d29c32 Mon Sep 17 00:00:00 2001 From: Suomm <1474983351@qq.com> Date: Sat, 15 Jul 2023 17:49:54 +0800 Subject: [PATCH 4/8] =?UTF-8?q?refactor:=20=E9=80=9A=E8=BF=87=20builder=20?= =?UTF-8?q?=E6=9E=84=E5=BB=BA=20FieldQuery=20=E5=AF=B9=E8=B1=A1=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mybatisflex/core/field/FieldQuery.java | 111 ++++++++++++++++-- 1 file changed, 99 insertions(+), 12 deletions(-) diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/field/FieldQuery.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/field/FieldQuery.java index 31b91e80..34718eff 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/field/FieldQuery.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/field/FieldQuery.java @@ -15,29 +15,116 @@ */ 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 { + + 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 fieldType(FieldType fieldType) { + this.fieldQuery.setFieldType(fieldType); + return this; + } + + /** + * 阻止对嵌套类属性的查询,只对 {@link FieldType#COLLECTION} 与 + * {@link FieldType#ENTITY} 两种属性类型有效。 + * + * @return 构建者 + */ + public Builder prevent() { + this.fieldQuery.setPrevent(true); + return this; + } + + /** + * 设置是否阻止对嵌套类属性的查询,只对 {@link FieldType#COLLECTION} 与 + * {@link FieldType#ENTITY} 两种属性类型有效。 + * + * @param prevent 是否阻止对嵌套类属性查询 + * @return 构建者 + */ + public Builder prevent(boolean prevent) { + this.fieldQuery.setPrevent(prevent); + return this; + } + + /** + * 设置查询这个属性的 {@code QueryWrapper} 对象。 + * + * @param queryBuilder 查询包装器 + * @return 构建者 + */ + public Builder queryWrapper(QueryBuilder queryBuilder) { + this.fieldQuery.setQueryBuilder(queryBuilder); + return this; + } + + protected FieldQuery build() { + return this.fieldQuery; + } + } } From 7a1523bd779582486f4274c59de0bfcbd915c3a8 Mon Sep 17 00:00:00 2001 From: Suomm <1474983351@qq.com> Date: Sat, 15 Jul 2023 17:50:32 +0800 Subject: [PATCH 5/8] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=20FieldQueryMana?= =?UTF-8?q?ger=20=E5=A4=84=E7=90=86=E5=B1=9E=E6=80=A7=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/field/FieldQueryManager.java | 171 ++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 mybatis-flex-core/src/main/java/com/mybatisflex/core/field/FieldQueryManager.java diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/field/FieldQueryManager.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/field/FieldQueryManager.java new file mode 100644 index 00000000..f7495416 --- /dev/null +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/field/FieldQueryManager.java @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * 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 + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * 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 fieldQueryMap) { + for (Object entity : entities) { + Class entityClass = entity.getClass(); + List 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 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 Object getArrayValue(Class componentType, List 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; + } + +} From d867a2671cfa22c530a8833f1f3b6b00787da173 Mon Sep 17 00:00:00 2001 From: Suomm <1474983351@qq.com> Date: Sat, 15 Jul 2023 17:51:29 +0800 Subject: [PATCH 6/8] =?UTF-8?q?refactor:=20=E8=B0=83=E7=94=A8=20FieldQuery?= =?UTF-8?q?Manager=20=E5=A4=84=E7=90=86=E5=B1=9E=E6=80=A7=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mybatisflex/core/util/MapperUtil.java | 41 ++++++------------- 1 file changed, 12 insertions(+), 29 deletions(-) diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/util/MapperUtil.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/util/MapperUtil.java index 629e2426..ee693752 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/util/MapperUtil.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/util/MapperUtil.java @@ -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 void queryFields(BaseMapper mapper, List list, Consumer>[] consumers) { if (CollectionUtil.isEmpty(list) || ArrayUtil.isEmpty(consumers) || consumers[0] == null) { return; } - list.forEach(entity -> { - for (Consumer> consumer : consumers) { - FieldQueryBuilder fieldQueryBuilder = new FieldQueryBuilder<>(entity); - consumer.accept(fieldQueryBuilder); - FieldQuery fieldQuery = fieldQueryBuilder.build(); - QueryWrapper childQuery = fieldQuery.getQueryWrapper(); - FieldWrapper fieldWrapper = FieldWrapper.of(entity.getClass(), fieldQuery.getField()); + Map fieldQueryMap = new HashMap<>(); + for (Consumer> consumer : consumers) { + FieldQueryBuilder 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 = getWrapType(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); } From 3575c6894b6417d08a6434061f1aa015720dceaa Mon Sep 17 00:00:00 2001 From: Suomm <1474983351@qq.com> Date: Sat, 15 Jul 2023 17:52:00 +0800 Subject: [PATCH 7/8] =?UTF-8?q?test:=20=E6=9B=B4=E6=96=B0=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mybatisflex/test/AccountTester.java | 3 +- .../com/mybatisflex/test/model/UserInfo.java | 43 ----------- .../com/mybatisflex/test/model/UserVO.java | 12 +-- .../test/mapper/UserMapperTest.java | 74 ++++++++++++++++++- 4 files changed, 80 insertions(+), 52 deletions(-) diff --git a/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/AccountTester.java b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/AccountTester.java index e1d29f1c..cacebf20 100644 --- a/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/AccountTester.java +++ b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/AccountTester.java @@ -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); diff --git a/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/java/com/mybatisflex/test/model/UserInfo.java b/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/java/com/mybatisflex/test/model/UserInfo.java index 1ba29747..d83b8773 100644 --- a/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/java/com/mybatisflex/test/model/UserInfo.java +++ b/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/java/com/mybatisflex/test/model/UserInfo.java @@ -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; - } - } diff --git a/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/java/com/mybatisflex/test/model/UserVO.java b/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/java/com/mybatisflex/test/model/UserVO.java index 5ef336af..d75318ea 100644 --- a/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/java/com/mybatisflex/test/model/UserVO.java +++ b/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/java/com/mybatisflex/test/model/UserVO.java @@ -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 roleList; + // private TreeSet roleList; +// private Role[] roleList; + private HashMap roleList; public String getUserId() { return userId; @@ -48,11 +50,11 @@ public class UserVO { this.userName = userName; } - public Collection getRoleList() { + public Map getRoleList() { return roleList; } - public void setRoleList(TreeSet roleList) { + public void setRoleList(HashMap roleList) { this.roleList = roleList; } diff --git a/mybatis-flex-test/mybatis-flex-spring-boot-test/src/test/java/com/mybatisflex/test/mapper/UserMapperTest.java b/mybatis-flex-test/mybatis-flex-spring-boot-test/src/test/java/com/mybatisflex/test/mapper/UserMapperTest.java index fcfbf23d..16b38f7d 100644 --- a/mybatis-flex-test/mybatis-flex-spring-boot-test/src/test/java/com/mybatisflex/test/mapper/UserMapperTest.java +++ b/mybatis-flex-test/mybatis-flex-spring-boot-test/src/test/java/com/mybatisflex/test/mapper/UserMapperTest.java @@ -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 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 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 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 userInfos2 = userMapper.selectListWithRelationsByQueryAs(queryWrapper2, UserInfo.class); - userInfos2.forEach(System.err::println); - Assertions.assertEquals(userInfos1, userInfos2); + List 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 From 9b51a063d2e4bbea16c543aa49043a763b7a8aae Mon Sep 17 00:00:00 2001 From: Suomm <1474983351@qq.com> Date: Sat, 15 Jul 2023 20:19:15 +0800 Subject: [PATCH 8/8] style: javadoc --- .../java/com/mybatisflex/core/field/FieldQuery.java | 3 +++ .../java/com/mybatisflex/core/field/FieldType.java | 2 +- .../java/com/mybatisflex/core/field/QueryBuilder.java | 11 +++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/field/FieldQuery.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/field/FieldQuery.java index 34718eff..900aab1c 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/field/FieldQuery.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/field/FieldQuery.java @@ -17,6 +17,9 @@ package com.mybatisflex.core.field; import java.io.Serializable; +/** + * 查询属性的信息。 + */ @SuppressWarnings("rawtypes") public class FieldQuery implements Serializable { diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/field/FieldType.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/field/FieldType.java index 158f635b..c8941bbd 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/field/FieldType.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/field/FieldType.java @@ -84,7 +84,7 @@ public enum FieldType { ); /** - * 自动推断属性类型 + * 自动推断属性类型。 * * @param field 属性 * @return 属性类型 diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/field/QueryBuilder.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/field/QueryBuilder.java index 04250848..7f89e665 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/field/QueryBuilder.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/field/QueryBuilder.java @@ -17,8 +17,19 @@ package com.mybatisflex.core.field; import com.mybatisflex.core.query.QueryWrapper; +/** + * 属性查询条件构建。 + * + * @param 实体类类型 + */ public interface QueryBuilder { + /** + * 构建查询属性的 {@link QueryWrapper} 对象。 + * + * @param entity 实体类 + * @return 查询条件 + */ QueryWrapper build(T entity); }