瀏覽代碼

【功能修复】代码生成:代同步数据库结构之后字段顺序混乱的问题

YunaiV 8 月之前
父節點
當前提交
42b7946685

+ 5 - 0
yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/RandomUtils.java

@@ -134,6 +134,11 @@ public class RandomUtils {
     @SafeVarargs
     public static <T> List<T> randomPojoList(Class<T> clazz, Consumer<T>... consumers) {
         int size = RandomUtil.randomInt(1, RANDOM_COLLECTION_LENGTH);
+        return randomPojoList(clazz, size, consumers);
+    }
+
+    @SafeVarargs
+    public static <T> List<T> randomPojoList(Class<T> clazz, int size, Consumer<T>... consumers) {
         return Stream.iterate(0, i -> i).limit(size).map(o -> randomPojo(clazz, consumers))
                 .collect(Collectors.toList());
     }

+ 1 - 1
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/codegen/CodegenColumnMapper.java

@@ -13,7 +13,7 @@ public interface CodegenColumnMapper extends BaseMapperX<CodegenColumnDO> {
     default List<CodegenColumnDO> selectListByTableId(Long tableId) {
         return selectList(new LambdaQueryWrapperX<CodegenColumnDO>()
                 .eq(CodegenColumnDO::getTableId, tableId)
-                .orderByAsc(CodegenColumnDO::getId));
+                .orderByAsc(CodegenColumnDO::getOrdinalPosition));
     }
 
     default void deleteListByTableId(Long tableId) {

+ 14 - 6
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenServiceImpl.java

@@ -22,13 +22,14 @@ import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
 import com.baomidou.mybatisplus.generator.config.po.TableField;
 import com.baomidou.mybatisplus.generator.config.po.TableInfo;
 import com.google.common.annotations.VisibleForTesting;
+import jakarta.annotation.Resource;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import jakarta.annotation.Resource;
 import java.util.*;
 import java.util.function.BiPredicate;
 import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
@@ -179,11 +180,18 @@ public class CodegenServiceImpl implements CodegenService {
                         && tableField.getMetaInfo().isNullable() == codegenColumn.getNullable()
                         && tableField.isKeyFlag() == codegenColumn.getPrimaryKey()
                         && tableField.getComment().equals(codegenColumn.getColumnComment());
-        Set<String> modifyFieldNames = tableFields.stream()
-                .filter(tableField -> codegenColumnDOMap.get(tableField.getColumnName()) != null
-                        && !primaryKeyPredicate.test(tableField, codegenColumnDOMap.get(tableField.getColumnName())))
-                .map(TableField::getColumnName)
-                .collect(Collectors.toSet());
+        Set<String> modifyFieldNames = IntStream.range(0, tableFields.size()).mapToObj(index -> {
+            TableField tableField = tableFields.get(index);
+            String columnName = tableField.getColumnName();
+            CodegenColumnDO codegenColumn = codegenColumnDOMap.get(columnName);
+            if (codegenColumn == null) {
+                return null;
+            }
+            if (!primaryKeyPredicate.test(tableField, codegenColumn) || codegenColumn.getOrdinalPosition() != index) {
+                return columnName;
+            }
+            return null;
+        }).filter(Objects::nonNull).collect(Collectors.toSet());
         // 3.2 计算需要【删除】的字段
         Set<String> tableFieldNames = convertSet(tableFields, TableField::getName);
         Set<Long> deleteColumnIds = codegenColumns.stream()

+ 12 - 10
yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenServiceImplTest.java

@@ -24,12 +24,11 @@ import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
 import com.baomidou.mybatisplus.generator.config.po.TableField;
 import com.baomidou.mybatisplus.generator.config.po.TableInfo;
-import org.junit.jupiter.api.Disabled;
+import jakarta.annotation.Resource;
 import org.junit.jupiter.api.Test;
 import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.context.annotation.Import;
 
-import jakarta.annotation.Resource;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
@@ -234,17 +233,16 @@ public class CodegenServiceImplTest extends BaseDbUnitTest {
     }
 
     @Test
-    @Disabled // TODO @芋艿:这个单测会随机性失败,需要定位下;
     public void testSyncCodegenFromDB() {
         // mock 数据(CodegenTableDO)
         CodegenTableDO table = randomPojo(CodegenTableDO.class, o -> o.setTableName("t_yunai")
                 .setDataSourceConfigId(1L).setScene(CodegenSceneEnum.ADMIN.getScene()));
         codegenTableMapper.insert(table);
         CodegenColumnDO column01 = randomPojo(CodegenColumnDO.class, o -> o.setTableId(table.getId())
-                .setColumnName("id"));
+                .setColumnName("id").setPrimaryKey(true).setOrdinalPosition(0));
         codegenColumnMapper.insert(column01);
         CodegenColumnDO column02 = randomPojo(CodegenColumnDO.class, o -> o.setTableId(table.getId())
-                .setColumnName("name"));
+                .setColumnName("name").setOrdinalPosition(1));
         codegenColumnMapper.insert(column02);
         // 准备参数
         Long tableId = table.getId();
@@ -263,7 +261,7 @@ public class CodegenServiceImplTest extends BaseDbUnitTest {
         when(databaseTableService.getTable(eq(1L), eq("t_yunai")))
                 .thenReturn(tableInfo);
         // mock 方法(CodegenTableDO)
-        List<CodegenColumnDO> newColumns = randomPojoList(CodegenColumnDO.class);
+        List<CodegenColumnDO> newColumns = randomPojoList(CodegenColumnDO.class, 2);
         when(codegenBuilder.buildColumns(eq(table.getId()), argThat(tableFields -> {
             assertEquals(2, tableFields.size());
             assertSame(tableInfo.getFields(), tableFields);
@@ -457,9 +455,11 @@ public class CodegenServiceImplTest extends BaseDbUnitTest {
                         .setTemplateType(CodegenTemplateTypeEnum.ONE.getType()));
         codegenTableMapper.insert(table);
         // mock 数据(CodegenColumnDO)
-        CodegenColumnDO column01 = randomPojo(CodegenColumnDO.class, o -> o.setTableId(table.getId()));
+        CodegenColumnDO column01 = randomPojo(CodegenColumnDO.class, o -> o.setTableId(table.getId())
+                .setOrdinalPosition(1));
         codegenColumnMapper.insert(column01);
-        CodegenColumnDO column02 = randomPojo(CodegenColumnDO.class, o -> o.setTableId(table.getId()));
+        CodegenColumnDO column02 = randomPojo(CodegenColumnDO.class, o -> o.setTableId(table.getId())
+                .setOrdinalPosition(2));
         codegenColumnMapper.insert(column02);
         // mock 执行生成
         Map<String, String> codes = MapUtil.of(randomString(), randomString());
@@ -486,9 +486,11 @@ public class CodegenServiceImplTest extends BaseDbUnitTest {
                         .setTemplateType(CodegenTemplateTypeEnum.MASTER_NORMAL.getType()));
         codegenTableMapper.insert(table);
         // mock 数据(CodegenColumnDO)
-        CodegenColumnDO column01 = randomPojo(CodegenColumnDO.class, o -> o.setTableId(table.getId()));
+        CodegenColumnDO column01 = randomPojo(CodegenColumnDO.class, o -> o.setTableId(table.getId())
+                .setOrdinalPosition(1));
         codegenColumnMapper.insert(column01);
-        CodegenColumnDO column02 = randomPojo(CodegenColumnDO.class, o -> o.setTableId(table.getId()));
+        CodegenColumnDO column02 = randomPojo(CodegenColumnDO.class, o -> o.setTableId(table.getId())
+                .setOrdinalPosition(2));
         codegenColumnMapper.insert(column02);
         // mock 数据(sub CodegenTableDO)
         CodegenTableDO subTable = randomPojo(CodegenTableDO.class,