From 4cc7fdb4e7abd4efdb35faa895b32c7b6df16bb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=80=E6=BA=90=E6=B5=B7=E5=93=A5?= Date: Tue, 13 Jun 2023 13:01:40 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=20TableInfo.buildResultMap?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/mybatis/FlexConfiguration.java | 51 +------- .../com/mybatisflex/core/table/TableInfo.java | 121 ++---------------- .../java/com/mybatisflex/test/AccountDTO.java | 104 +++++++++++++++ .../com/mybatisflex/test/JoinTestStarter.java | 69 ++++++++++ .../src/main/resources/application.yml | 4 +- .../resources/{use_test.sql => user_test.sql} | 41 ++---- 6 files changed, 204 insertions(+), 186 deletions(-) create mode 100644 mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/AccountDTO.java create mode 100644 mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/JoinTestStarter.java rename mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/resources/{use_test.sql => user_test.sql} (79%) diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/FlexConfiguration.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/FlexConfiguration.java index 15de5227..af7b4994 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/FlexConfiguration.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/FlexConfiguration.java @@ -36,15 +36,16 @@ import org.apache.ibatis.executor.keygen.SelectKeyGenerator; import org.apache.ibatis.executor.parameter.ParameterHandler; import org.apache.ibatis.executor.resultset.ResultSetHandler; import org.apache.ibatis.executor.statement.StatementHandler; -import org.apache.ibatis.mapping.*; +import org.apache.ibatis.mapping.BoundSql; +import org.apache.ibatis.mapping.Environment; +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.ibatis.mapping.ResultMap; import org.apache.ibatis.session.*; import org.apache.ibatis.transaction.Transaction; import org.apache.ibatis.util.MapUtil; import java.lang.reflect.Proxy; -import java.util.ArrayList; import java.util.Collections; -import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -189,37 +190,11 @@ public class FlexConfiguration extends Configuration { String resultMapId = tableInfo.getEntityClass().getName(); - /*ResultMap resultMap; + ResultMap resultMap; if (hasResultMap(resultMapId)) { resultMap = getResultMap(resultMapId); } else { resultMap = tableInfo.buildResultMap(this); - this.addResultMap(resultMap); - }*/ - - // 变量名与属性名区分开 - List resultMapList; - if (hasResultMap(resultMapId)) { - resultMapList = new ArrayList<>(); - fillResultMapList(resultMapId, resultMapList); - } else { - resultMapList = tableInfo.buildResultMapList(this); - for (ResultMap resultMap : resultMapList) { - if (!hasResultMap(resultMap.getId())) { - addResultMap(resultMap); - } - } - /* - * 这里解释一下为什么要反转这个集合: - * - * MyBatis 在解析 ResultMaps 的时候,是按照顺序一个一个进行解析的,对于有嵌套 - * 的 ResultMap 对象,也就是 nestResultMap 需要放在靠前的位置,首先解析。 - * - * 而我们进行递归 buildResultMapList 是非嵌套 ResultMap 在集合最开始的位置, - * 所以要反转一下集合,将 hasNestedResultMaps 的 ResultMap 对象放到集合的最 - * 前面。 - */ - Collections.reverse(resultMapList); } return new MappedStatement.Builder(ms.getConfiguration(), ms.getId(), ms.getSqlSource(), ms.getSqlCommandType()) @@ -234,8 +209,7 @@ public class FlexConfiguration extends Configuration { .lang(ms.getLang()) .resultOrdered(ms.isResultOrdered()) .resultSets(ms.getResultSets() == null ? null : String.join(",", ms.getResultSets())) - //.resultMaps(CollectionUtil.newArrayList(resultMap)) // 替换resultMap - .resultMaps(resultMapList) + .resultMaps(Collections.singletonList(resultMap)) .resultSetType(ms.getResultSetType()) .flushCacheRequired(ms.isFlushCacheRequired()) .useCache(ms.isUseCache()) @@ -243,19 +217,6 @@ public class FlexConfiguration extends Configuration { .build(); } - private void fillResultMapList(String resultMapId, List resultMapList) { - ResultMap resultMap = this.getResultMap(resultMapId); - resultMapList.add(resultMap); - if (resultMap.hasNestedResultMaps()) { - for (ResultMapping resultMapping : resultMap.getResultMappings()) { - String nestedResultMapId = resultMapping.getNestedResultMapId(); - if (nestedResultMapId != null) { - fillResultMapList(nestedResultMapId, resultMapList); - } - } - } - } - /** * 生成新的、已替换主键生成器的 MappedStatement * diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/table/TableInfo.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/table/TableInfo.java index a21547ad..eb97d66f 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/table/TableInfo.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/table/TableInfo.java @@ -706,80 +706,12 @@ public class TableInfo { .collect(Collectors.toList()); } - /** - * @deprecated 该功能有更好的方式实现,此方法可能会被移除。 - */ - @Deprecated + public ResultMap buildResultMap(Configuration configuration) { String resultMapId = entityClass.getName(); - List resultMappings = new ArrayList<>(); - - for (ColumnInfo columnInfo : columnInfoList) { - ResultMapping mapping = new ResultMapping.Builder(configuration, columnInfo.property, - columnInfo.column, columnInfo.propertyType) - .jdbcType(columnInfo.getJdbcType()) - .typeHandler(columnInfo.buildTypeHandler()) - .build(); - resultMappings.add(mapping); - - //add property mapper for sql: select xxx as property ... - if (!Objects.equals(columnInfo.getColumn(), columnInfo.getProperty())) { - ResultMapping propertyMapping = new ResultMapping.Builder(configuration, columnInfo.property, - columnInfo.property, columnInfo.propertyType) - .jdbcType(columnInfo.getJdbcType()) - .typeHandler(columnInfo.buildTypeHandler()) - .build(); - resultMappings.add(propertyMapping); - } + if (configuration.hasResultMap(resultMapId)) { + return configuration.getResultMap(resultMapId); } - - for (IdInfo idInfo : primaryKeyList) { - ResultMapping mapping = new ResultMapping.Builder(configuration, idInfo.property, - idInfo.column, idInfo.propertyType) - .flags(CollectionUtil.newArrayList(ResultFlag.ID)) - .jdbcType(idInfo.getJdbcType()) - .typeHandler(idInfo.buildTypeHandler()) - .build(); - resultMappings.add(mapping); - } - - if (joinTypes != null && !joinTypes.isEmpty()) { - joinTypes.forEach((fieldName, fieldType) -> { - - TableInfo joinTableInfo = TableInfoFactory.ofEntityClass(fieldType); - List joinTableInfoColumnInfoList = joinTableInfo.getColumnInfoList(); - - for (ColumnInfo joinColumnInfo : joinTableInfoColumnInfoList) { - if (!existColumn(resultMappings, joinColumnInfo.column)) { - ResultMapping mapping = new ResultMapping.Builder(configuration, fieldName + "." + joinColumnInfo.property, - joinColumnInfo.column, joinColumnInfo.propertyType) - .jdbcType(joinColumnInfo.jdbcType) - .typeHandler(joinColumnInfo.buildTypeHandler()) - .build(); - resultMappings.add(mapping); - } - - //add property mapper for sql: select xxx as property ... - if (!existColumn(resultMappings, joinColumnInfo.property)) { - if (!Objects.equals(joinColumnInfo.column, joinColumnInfo.property)) { - ResultMapping propertyMapping = new ResultMapping.Builder(configuration, fieldName + "." + joinColumnInfo.property, - joinColumnInfo.property, joinColumnInfo.propertyType) - .jdbcType(joinColumnInfo.jdbcType) - .typeHandler(joinColumnInfo.buildTypeHandler()) - .build(); - resultMappings.add(propertyMapping); - } - } - } - }); - } - - return new ResultMap.Builder(configuration, resultMapId, entityClass, resultMappings).build(); - } - - public List buildResultMapList(Configuration configuration) { - String resultMapId = entityClass.getName(); - List resultMaps = new ArrayList<>(); List resultMappings = new ArrayList<>(); // 标签下的 标签映射 @@ -819,19 +751,11 @@ public class TableInfo { // 获取嵌套类型的信息,也就是 javaType 属性 TableInfo tableInfo = TableInfoFactory.ofEntityClass(fieldType); // 构建嵌套类型的 ResultMap 对象,也就是 标签下的内容 - // 这里是递归调用,直到嵌套类型里面没有其他嵌套类型或者集合类型为止 - List resultMapList = tableInfo.buildResultMapList(configuration); - // 寻找是否有嵌套 ResultMap 引用 - Optional nestedResultMap = resultMapList.stream() - .filter(e -> fieldType.getName().equals(e.getId())) - .findFirst(); - // 处理嵌套类型 ResultMapping 引用 - nestedResultMap.ifPresent(resultMap -> resultMappings.add(new ResultMapping.Builder(configuration, fieldName) + ResultMap nestedResultMap = tableInfo.buildResultMap(configuration); + resultMappings.add(new ResultMapping.Builder(configuration, fieldName) .javaType(fieldType) - .nestedResultMapId(resultMap.getId()) - .build())); - // 全部添加到 ResultMap 集合当中 - resultMaps.addAll(resultMapList); + .nestedResultMapId(nestedResultMap.getId()) + .build()); }); } @@ -841,34 +765,17 @@ public class TableInfo { // 获取集合泛型类型的信息,也就是 ofType 属性 TableInfo tableInfo = TableInfoFactory.ofEntityClass(genericClass); // 构建嵌套类型的 ResultMap 对象,也就是 标签下的内容 - // 这里是递归调用,直到集合类型里面没有其他嵌套类型或者集合类型为止 - List resultMapList = tableInfo.buildResultMapList(configuration); - // 寻找是否有嵌套 ResultMap 引用 - Optional nestedResultMap = resultMapList.stream() - .filter(e -> genericClass.getName().equals(e.getId())) - .findFirst(); - // 处理嵌套类型 ResultMapping 引用 - nestedResultMap.ifPresent(resultMap -> resultMappings.add(new ResultMapping.Builder(configuration, field.getName()) + ResultMap nestedResultMap = tableInfo.buildResultMap(configuration); + resultMappings.add(new ResultMapping.Builder(configuration, field.getName()) .javaType(field.getType()) - .nestedResultMapId(resultMap.getId()) - .build())); - // 全部添加到 ResultMap 集合当中 - resultMaps.addAll(resultMapList); + .nestedResultMapId(nestedResultMap.getId()) + .build()); }); } - resultMaps.add(new ResultMap.Builder(configuration, resultMapId, entityClass, resultMappings).build()); - - return resultMaps; - } - - private static boolean existColumn(List resultMappings, String name) { - for (ResultMapping resultMapping : resultMappings) { - if (resultMapping.getColumn().equalsIgnoreCase(name)) { - return true; - } - } - return false; + ResultMap resultMap = new ResultMap.Builder(configuration, resultMapId, entityClass, resultMappings).build(); + configuration.addResultMap(resultMap); + return resultMap; } diff --git a/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/AccountDTO.java b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/AccountDTO.java new file mode 100644 index 00000000..3756e50c --- /dev/null +++ b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/AccountDTO.java @@ -0,0 +1,104 @@ +package com.mybatisflex.test; + +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.ColumnMask; +import com.mybatisflex.core.handler.Fastjson2TypeHandler; +import com.mybatisflex.core.mask.Masks; + +import javax.validation.constraints.NotBlank; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class AccountDTO { + + + private Long id; + + @ColumnMask(Masks.CHINESE_NAME) + private String userName; + + private int age; + + @NotBlank + private Date birthday; + + @Column(typeHandler = Fastjson2TypeHandler.class, isLarge = true) + private Map options; + + @Column(isLogicDelete = true) + private Boolean isDelete; + + private List
articles; + + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + + public Date getBirthday() { + return birthday; + } + + public void setBirthday(Date birthday) { + this.birthday = birthday; + } + + public Map getOptions() { + return options; + } + + public void setOptions(Map options) { + this.options = options; + } + + public void addOption(String key, Object value) { + if (options == null) { + options = new HashMap<>(); + } + options.put(key, value); + } + + public Boolean getDelete() { + return isDelete; + } + + public void setDelete(Boolean delete) { + isDelete = delete; + } + + public List
getArticles() { + return articles; + } + + public void setArticles(List
articles) { + this.articles = articles; + } + + @Override + public String toString() { + return "AccountDTO{" + + "id=" + id + + ", userName='" + userName + '\'' + + ", age=" + age + + ", birthday=" + birthday + + ", options=" + options + + ", isDelete=" + isDelete + + ", articles=" + articles + + '}'; + } +} diff --git a/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/JoinTestStarter.java b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/JoinTestStarter.java new file mode 100644 index 00000000..667ac684 --- /dev/null +++ b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/JoinTestStarter.java @@ -0,0 +1,69 @@ +/** + * 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.test; + +import com.mybatisflex.core.MybatisFlexBootstrap; +import com.mybatisflex.core.audit.AuditManager; +import com.mybatisflex.core.audit.ConsoleMessageCollector; +import com.mybatisflex.core.audit.MessageCollector; +import com.mybatisflex.core.query.QueryWrapper; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; + +import javax.sql.DataSource; +import java.util.List; + +public class JoinTestStarter { + + public static void main(String[] args) { + DataSource dataSource = new EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.H2) + .addScript("schema.sql") + .addScript("data.sql") + .build(); + + MybatisFlexBootstrap bootstrap = MybatisFlexBootstrap.getInstance() + .setDataSource(dataSource) + .addMapper(AccountMapper.class) + .addMapper(MyAccountMapper.class) + .start(); + + //开启审计功能 + AuditManager.setAuditEnable(true); + + //设置 SQL 审计收集器 + MessageCollector collector = new ConsoleMessageCollector(); + AuditManager.setMessageCollector(collector); + + + AccountMapper accountMapper = bootstrap.getMapper(AccountMapper.class); + + +// List accounts = accountMapper.selectListByQuery(QueryWrapper.create()); +// System.out.println(accounts); + + List accountDTOS = accountMapper.selectListByQueryAs(QueryWrapper.create(),AccountDTO.class); + System.out.println(accountDTOS); + +// +// List articleDTOS = accountMapper.selectListByQueryAs(QueryWrapper.create(), ArticleDTO.class); +// System.out.println(articleDTOS); +// +// +// Page paginate = accountMapper.paginateAs(Page.of(1, 10), QueryWrapper.create(), ArticleDTO01.class); +// System.out.println(paginate); + } +} diff --git a/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/resources/application.yml b/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/resources/application.yml index abbcedf7..11c63634 100644 --- a/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/resources/application.yml +++ b/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/resources/application.yml @@ -5,9 +5,9 @@ spring: # enabled: true datasource: driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://localhost:3306/mp_test + url: jdbc:mysql://localhost:3306/flex_test username: root - password: 12345678 + password: 123456 # sql: # init: # schema-locations: classpath:schema.sql diff --git a/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/resources/use_test.sql b/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/resources/user_test.sql similarity index 79% rename from mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/resources/use_test.sql rename to mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/resources/user_test.sql index 8404200c..b9f5d9de 100644 --- a/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/resources/use_test.sql +++ b/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/resources/user_test.sql @@ -1,19 +1,3 @@ -/* - Navicat Premium Data Transfer - - Source Server : MySQL3306 - Source Server Type : MySQL - Source Server Version : 80024 - Source Host : localhost:3306 - Source Schema : mp_test - - Target Server Type : MySQL - Target Server Version : 80024 - File Encoding : 65001 - - Date: 08/06/2023 19:48:10 -*/ - SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; @@ -23,13 +7,12 @@ SET FOREIGN_KEY_CHECKS = 0; DROP TABLE IF EXISTS `tb_good`; CREATE TABLE `tb_good` ( - `good_id` int NOT NULL AUTO_INCREMENT, - `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, - `price` decimal(10, 2) NULL DEFAULT NULL, + `good_id` int NOT NULL AUTO_INCREMENT, + `name` varchar(255) CHARACTER SET utf8mb4 NULL DEFAULT NULL, + `price` decimal(10, 2) NULL DEFAULT NULL, PRIMARY KEY (`good_id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 - COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; -- ---------------------------- @@ -67,7 +50,6 @@ CREATE TABLE `tb_order` PRIMARY KEY (`order_id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 - COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; -- ---------------------------- @@ -96,7 +78,6 @@ CREATE TABLE `tb_order_good` `good_id` int NOT NULL ) ENGINE = InnoDB CHARACTER SET = utf8mb4 - COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; -- ---------------------------- @@ -135,13 +116,12 @@ VALUES (6, 10); DROP TABLE IF EXISTS `tb_role`; CREATE TABLE `tb_role` ( - `role_id` int NOT NULL AUTO_INCREMENT, - `role_key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, - `role_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, + `role_id` int NOT NULL AUTO_INCREMENT, + `role_key` varchar(255) CHARACTER SET utf8mb4 NULL DEFAULT NULL, + `role_name` varchar(255) CHARACTER SET utf8mb4 NULL DEFAULT NULL, PRIMARY KEY (`role_id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 - COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; -- ---------------------------- @@ -162,13 +142,12 @@ VALUES (4, 'admin', '管理员用户'); DROP TABLE IF EXISTS `tb_user`; CREATE TABLE `tb_user` ( - `user_id` int NOT NULL AUTO_INCREMENT, - `user_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, - `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, + `user_id` int NOT NULL AUTO_INCREMENT, + `user_name` varchar(255) CHARACTER SET utf8mb4 NULL DEFAULT NULL, + `password` varchar(255) CHARACTER SET utf8mb4 NULL DEFAULT NULL, PRIMARY KEY (`user_id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 - COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; -- ---------------------------- @@ -193,7 +172,6 @@ CREATE TABLE `tb_user_order` `order_id` int NOT NULL ) ENGINE = InnoDB CHARACTER SET = utf8mb4 - COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; -- ---------------------------- @@ -222,7 +200,6 @@ CREATE TABLE `tb_user_role` `role_id` int NOT NULL ) ENGINE = InnoDB CHARACTER SET = utf8mb4 - COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; -- ----------------------------