Browse Source

1. 自测数据迁移,并完成开发环境数据迁移。
2. 优化动态数据源创建过程,增加容错处理

yucheng 3 years ago
parent
commit
4c7999171f

+ 55 - 20
dmp-business/dmp-rwd/src/main/java/com/persagy/dmp/rwd/migrate/service/impl/DigitalMigrateServiceImpl.java

@@ -25,7 +25,6 @@ import java.util.Set;
  * @date 2021-08-04
  */
 @Service
-@Transactional(rollbackFor = Exception.class)
 @Slf4j
 public class DigitalMigrateServiceImpl implements IDigitalMigrateService {
 
@@ -39,6 +38,7 @@ public class DigitalMigrateServiceImpl implements IDigitalMigrateService {
             log.error("没有查询到集团信息!");
             return;
         }
+        log.info("#########数据迁移已启动##########");
         // 按集团循环处理
         for(String groupCode:groupCodeSet) {
             log.info(StrUtil.format("开始处理{}集团", groupCode));
@@ -48,14 +48,33 @@ public class DigitalMigrateServiceImpl implements IDigitalMigrateService {
                 log.info(StrUtil.format("结束处理{}集团:没有找到需要迁移的项目", groupCode));
                 continue;
             }
+            // 切换集团数据源
+            AppContext.getContext().setGroupCode(groupCode);
+            DynamicDataSourceHelper.loadDataSource();
             // 集团数据迁移
-            doMigrate(oldSchema, groupCode);
-            // 项目数据迁移
-            for(String projectId:projectIdSet) {
-                doMigrate(oldSchema, groupCode, projectId);
-            }
+            doMigrate(oldSchema, groupCode, projectIdSet);
             log.info(StrUtil.format("结束处理{}集团:迁移完成!!!", groupCode));
         }
+        log.info("#########数据迁移已结束##########");
+    }
+
+    /**
+     * 执行迁移,在此方法上启动事务
+     * @param schema
+     * @param groupCode
+     * @param projectIds
+     */
+    @Transactional(rollbackFor = Exception.class)
+    protected void doMigrate(String schema, String groupCode, Set<String> projectIds) {
+        // 变小写
+        groupCode = groupCode.toLowerCase();
+        // 集团数据迁移
+        doMigrate(schema, groupCode);
+        // 项目数据迁移
+        for(String projectId:projectIds) {
+            projectId = projectId.toLowerCase();
+            doMigrate(schema, groupCode, projectId);
+        }
     }
 
     /**
@@ -64,20 +83,31 @@ public class DigitalMigrateServiceImpl implements IDigitalMigrateService {
      * @param groupCode 集团编码
      */
     private void doMigrate(String schema, String groupCode) {
-        // 切换集团数据源
-        AppContext.getContext().setGroupCode(groupCode);
-        DynamicDataSourceHelper.loadDataSource();
-        // 变小写
-        groupCode = groupCode.toLowerCase();
         // 迁移
         log.info(StrUtil.format("正在处理{}集团:迁移类型定义数据...", groupCode));
-        dao.migrateDefineType(schema, groupCode);
+        try {
+            dao.migrateDefineType(schema, groupCode);
+        } catch (Exception e) {
+            log.error(StrUtil.format("正在处理{}集团:迁移类型定义数据失败:{}", groupCode, e.getMessage()));
+        }
         log.info(StrUtil.format("正在处理{}集团:迁移信息点定义数据...", groupCode));
-        dao.migrateDefineInfo(schema, groupCode);
+        try {
+            dao.migrateDefineInfo(schema, groupCode);
+        } catch (Exception e) {
+            log.error(StrUtil.format("正在处理{}集团:迁移信息点定义数据失败:{}", groupCode, e.getMessage()));
+        }
         log.info(StrUtil.format("正在处理{}集团:迁移图定义数据...", groupCode));
-        dao.migrateDefineGraph(schema, groupCode);
+        try {
+            dao.migrateDefineGraph(schema, groupCode);
+        } catch (Exception e) {
+            log.error(StrUtil.format("正在处理{}集团:迁移图定义数据失败:{}", groupCode, e.getMessage()));
+        }
         log.info(StrUtil.format("正在处理{}集团:迁移边定义数据...", groupCode));
-        dao.migrateDefineRel(schema, groupCode);
+        try {
+            dao.migrateDefineRel(schema, groupCode);
+        } catch (Exception e) {
+            log.error(StrUtil.format("正在处理{}集团:迁移边定义数据失败:{}", groupCode, e.getMessage()));
+        }
     }
 
     /**
@@ -87,14 +117,19 @@ public class DigitalMigrateServiceImpl implements IDigitalMigrateService {
      * @param projectId 项目ID
      */
     private void doMigrate(String schema, String groupCode, String projectId) {
-        // 已经切换到集团数据源了,不需要再切换了
-        groupCode = groupCode.toLowerCase();
-        projectId = projectId.toLowerCase();
         // 迁移
         log.info(StrUtil.format("正在处理{}集团{}项目:迁移对象数据...", groupCode, projectId));
-        dao.migrateObject(schema, groupCode, projectId);
+        try {
+            dao.migrateObject(schema, groupCode, projectId);
+        } catch (Exception e) {
+            log.error(StrUtil.format("正在处理{}集团{}项目:迁移对象数据失败:{}", groupCode, projectId, e.getMessage()));
+        }
         log.info(StrUtil.format("正在处理{}集团{}项目:迁移关系数据...", groupCode, projectId));
-        dao.migrateRelation(schema, groupCode, projectId);
+        try {
+            dao.migrateRelation(schema, groupCode, projectId);
+        } catch (Exception e) {
+            log.error(StrUtil.format("正在处理{}集团{}项目:迁移关系数据失败:{}", groupCode, projectId, e.getMessage()));
+        }
     }
 
     /**

+ 0 - 0
dmp-business/dmp-rwd/src/main/resources/db.init/data.sql


+ 1 - 0
dmp-business/dmp-rwd/src/main/resources/db/init/data.sql

@@ -0,0 +1 @@
+select 1 from dual;

dmp-business/dmp-rwd/src/main/resources/db.init/migrate.sql → dmp-business/dmp-rwd/src/main/resources/db/init/migrate.sql


+ 25 - 25
dmp-business/dmp-rwd/src/main/resources/db.init/schema.sql

@@ -1,16 +1,16 @@
 CREATE TABLE IF NOT EXISTS `dt_define_type` (
   `id` varchar(40) NOT NULL COMMENT '主键',
-  `code` varchar(60) NOT NULL COMMENT '编码-全局唯一',
+  `code` varchar(40) NOT NULL COMMENT '编码-全局唯一',
   `name` varchar(200) NOT NULL COMMENT '名称',
-  `alias_code` varchar(60) NOT NULL COMMENT '别名编码, 集团下唯一 ',
+  `alias_code` varchar(40) NOT NULL COMMENT '别名编码, 集团下唯一 ',
   `alias_name` varchar(200) NOT NULL COMMENT '别名名称',
   `obj_type` varchar(40) DEFAULT NULL COMMENT '大类型:项目建筑楼层空间系统设备竖井',
   `group_code` varchar(40) NOT NULL DEFAULT '0' COMMENT '集团编码',
   `project_id` varchar(40) NOT NULL DEFAULT '0' COMMENT '项目id',
-  `major_code` varchar(60) DEFAULT NULL COMMENT '专业编码, 上级类型是系统or设备时该字段有值',
-  `system_code` varchar(60) DEFAULT NULL COMMENT '系统编码,上级类型是设备时该字段有值,值为系统类型的code',
-  `equipment_code` varchar(60) DEFAULT NULL COMMENT '设备编码,上级类型是部件时该字段有值,值为设备类型的code',
-  `parent_code` varchar(60) DEFAULT NULL COMMENT '上级类型code,默认为"0"',
+  `major_code` varchar(40) DEFAULT NULL COMMENT '专业编码, 上级类型是系统or设备时该字段有值',
+  `system_code` varchar(40) DEFAULT NULL COMMENT '系统编码,上级类型是设备时该字段有值,值为系统类型的code',
+  `equipment_code` varchar(40) DEFAULT NULL COMMENT '设备编码,上级类型是部件时该字段有值,值为设备类型的code',
+  `parent_code` varchar(40) DEFAULT NULL COMMENT '上级类型code,默认为"0"',
   `version` varchar(40) DEFAULT NULL COMMENT '最后修改版本',
   `creator` varchar(32) DEFAULT NULL COMMENT '创建人',
   `creation_time` char(14) NULL DEFAULT NULL COMMENT '创建时间',
@@ -28,11 +28,11 @@ CREATE TABLE IF NOT EXISTS `dt_define_type` (
 
 CREATE TABLE IF NOT EXISTS `dt_define_info` (
   `id` varchar(40) NOT NULL,
-  `code` varchar(60) NOT NULL COMMENT '信息点编码,同类型下唯一,标准驼峰格式',
+  `code` varchar(100) NOT NULL COMMENT '信息点编码,同类型下唯一,标准驼峰格式',
   `name` varchar(200) DEFAULT NULL COMMENT '信息点名称',
-  `alias_code` varchar(60) DEFAULT NULL COMMENT '别名编码',
+  `alias_code` varchar(100) DEFAULT NULL COMMENT '别名编码',
   `alias_name` varchar(200) DEFAULT NULL COMMENT '别名名称',
-  `class_code` varchar(60) DEFAULT NULL COMMENT '类型编码',
+  `class_code` varchar(40) DEFAULT NULL COMMENT '类型编码',
   `group_code` varchar(40) NOT NULL DEFAULT '0' COMMENT '集团编码',
   `project_id` varchar(40) NOT NULL DEFAULT '0' COMMENT '项目id',
   `category` varchar(40) DEFAULT NULL COMMENT '信息点分类:静态,脉冲,阶段,时序',
@@ -42,9 +42,9 @@ CREATE TABLE IF NOT EXISTS `dt_define_info` (
   `input_mode` varchar(40) DEFAULT NULL COMMENT '输入方式',
   `unit` varchar(40) DEFAULT NULL COMMENT '单位',
   `data_type` varchar(40) DEFAULT NULL COMMENT '数据类型',
-  `multiple_flag` int(11) DEFAULT NULL COMMENT '是否复数',
-  `region_flag` int(11) DEFAULT NULL COMMENT '是否区间',
-  `formatter` varchar(40) DEFAULT NULL COMMENT '数据格式',
+  `is_multiple` int(11) DEFAULT NULL COMMENT '是否复数',
+  `is_region` int(11) DEFAULT NULL COMMENT '是否区间',
+  `formater` varchar(40) DEFAULT NULL COMMENT '数据格式',
   `data_source` json DEFAULT NULL COMMENT '数据源取值范围/枚举值清单等,根据dataType有不同的内容',
   `remark` text COMMENT '备注',
   `sub_flag` int(11) DEFAULT NULL COMMENT '子分类标记:是否可以按此信息点进行子分类替换,同一类型下目前只支持一个子分类信息点',
@@ -63,7 +63,7 @@ CREATE TABLE IF NOT EXISTS `dt_define_info` (
 
 CREATE TABLE IF NOT EXISTS `dt_define_graph` (
   `id` varchar(40) NOT NULL,
-  `code` varchar(60) DEFAULT NULL COMMENT '编码',
+  `code` varchar(40) DEFAULT NULL COMMENT '编码',
   `name` varchar(200) DEFAULT NULL COMMENT '名称',
   `first_category` varchar(40) DEFAULT NULL COMMENT '一级分类',
   `second_category` varchar(40) DEFAULT NULL COMMENT '二级分类',
@@ -81,9 +81,9 @@ CREATE TABLE IF NOT EXISTS `dt_define_graph` (
 
 CREATE TABLE IF NOT EXISTS `dt_define_rel` (
   `id` varchar(40) NOT NULL,
-  `code` varchar(60) DEFAULT NULL COMMENT '编码',
+  `code` varchar(40) DEFAULT NULL COMMENT '编码',
   `name` varchar(200) DEFAULT NULL COMMENT '名称',
-  `graph_code` varchar(60) DEFAULT NULL COMMENT '图编码',
+  `graph_code` varchar(40) DEFAULT NULL COMMENT '图编码',
   `directional` int(11) DEFAULT NULL COMMENT '边方向性',
   `attribute` varchar(255) DEFAULT NULL COMMENT '边属性',
   `target_objs` varchar(255) DEFAULT NULL COMMENT '主要连接对象',
@@ -107,7 +107,7 @@ CREATE TABLE IF NOT EXISTS `dt_object` (
   `group_code` varchar(40) DEFAULT NULL COMMENT '集团编码',
   `project_id` varchar(40) NOT NULL COMMENT '项目id',
   `obj_type` varchar(40) NOT NULL COMMENT '对象分类',
-  `class_code` varchar(60) NOT NULL COMMENT '对象类型编码',
+  `class_code` varchar(40) NOT NULL COMMENT '对象类型编码',
   `grouping` int(11) NOT NULL DEFAULT '1' COMMENT '1单个对象,2对象组',
   `infos` json DEFAULT NULL COMMENT '边类型编码',
   `virtual_codes` json DEFAULT NULL COMMENT '虚点清单',
@@ -130,11 +130,11 @@ CREATE TABLE IF NOT EXISTS `dt_relation` (
   `group_code` varchar(40) DEFAULT NULL,
   `project_id` varchar(40) NOT NULL,
   `graph_id` varchar(40) DEFAULT NULL COMMENT '图主键',
-  `graph_code` varchar(60) DEFAULT NULL COMMENT '图编码',
-  `rel_code` varchar(60) DEFAULT NULL COMMENT '关系编码',
-  `rel_value` varchar(45) DEFAULT NULL COMMENT '关系值',
-  `obj_from` varchar(40) DEFAULT NULL COMMENT '来源对象',
-  `obj_to` varchar(40) DEFAULT NULL COMMENT '目标对象',
+  `graph_code` varchar(40) DEFAULT NULL COMMENT '图编码',
+  `rel_code` varchar(40) DEFAULT NULL COMMENT '关系编码',
+  `rel_value` varchar(50) DEFAULT NULL COMMENT '关系值',
+  `obj_from` varchar(60) DEFAULT NULL COMMENT '来源对象',
+  `obj_to` varchar(60) DEFAULT NULL COMMENT '目标对象',
   `create_app` varchar(40) DEFAULT NULL COMMENT '创建应用',
   `update_app` varchar(40) DEFAULT NULL COMMENT '最后更新应用',
   `creator` varchar(32) DEFAULT NULL COMMENT '创建人',
@@ -145,8 +145,8 @@ CREATE TABLE IF NOT EXISTS `dt_relation` (
   `ts` timestamp default current_timestamp on update current_timestamp NOT NULL COMMENT '乐观锁',
   PRIMARY KEY (`id`) USING BTREE,
   KEY `idx_graph_code` (`graph_code`) USING BTREE,
-  KEY `idx_1` (`project_id`,`graph_code`,`rel_code`,`obj_from`,`obj_to`) USING BTREE,
-  KEY `idx_2` (`project_id`,`graph_id`,`rel_code`,`obj_from`,`obj_to`) USING BTREE,
-  KEY `idx_3` (`project_id`,`graph_code`,`rel_code`,`obj_to`) USING BTREE,
-  KEY `idx_4` (`project_id`,`graph_id`,`rel_code`,`obj_to`) USING BTREE
+  KEY `idx_1` (`graph_code`,`rel_code`,`obj_from`,`obj_to`,`project_id`) USING BTREE,
+  KEY `idx_2` (`graph_id`,`rel_code`,`obj_from`,`obj_to`,`project_id`) USING BTREE,
+  KEY `idx_3` (`graph_code`,`rel_code`,`obj_to`,`project_id`) USING BTREE,
+  KEY `idx_4` (`graph_id`,`rel_code`,`obj_to`,`project_id`) USING BTREE
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='关系实例表';

+ 1 - 1
dmp-business/dmp-rwd/src/main/resources/mapper/DigitalMigrateMapper.xml

@@ -17,7 +17,7 @@
         replace into `dt_define_info`(`id`,`code`,`name`,`alias_code`,
           `alias_name`,`class_code`,`group_code`,`project_id`,`category`,
           `first_tag`,`second_tag`,`priority`,`input_mode`,`unit`,`data_type`,
-          `multiple_flag`,`region_flag`,`formatter`,`data_source`,`remark`,
+          `is_multiple`,`is_region`,`formater`,`data_source`,`remark`,
           `sub_flag`,`weak_point`,`show_order`,`version`,
           `creator`,`creation_time`,`modifier`,`modified_time`,`valid`)
         SELECT `id`,`code`,`name`,`alias_code`,

+ 49 - 17
dmp-comp/dmp-mybatis/src/main/java/com/persagy/dmp/mybatis/handler/DynamicDataSourceHandler.java

@@ -7,7 +7,6 @@ import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourcePrope
 import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
 import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
 import com.persagy.dmp.common.context.AppContext;
-import com.persagy.dmp.common.helper.SpringHelper;
 import com.persagy.dmp.mybatis.service.IDbService;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -57,40 +56,73 @@ public class DynamicDataSourceHandler extends HandlerInterceptorAdapter {
         if(!dynamicEnabled) {
             return;
         }
-        // 默认为应用名
-        String dbNameDefault = SpringHelper.getString("spring.application.name");
-        // 创建的数据源名称: 集团编码_应用名
-        String newDsName = AppContext.getContext().getGroupCode() + "_" + dbNameDefault;
-        // 大小写处理:全部小写
-        newDsName = newDsName.toLowerCase();
+        // 读取初始实例名
+        String defaultSchema = getPrimarySchema();
+        // 待切换的数据源名称: 初始实例名_集团编码
+        String newSchema = getNewSchema(defaultSchema);
         // 数据源中是否已存在
-        if(!dataSource.getCurrentDataSources().keySet().contains(newDsName)) {
+        if(!dataSource.getCurrentDataSources().keySet().contains(newSchema)) {
             // 设置新数据源
-            DataSourceProperty property = copyProperty(dbNameDefault, newDsName);
+            DataSourceProperty property = copyProperty(defaultSchema, newSchema);
             // 创建数据库实例
-            dbService.createDataBase(newDsName);
+            dbService.createDataBase(newSchema);
             // 创建数据源
             DataSource currDs = dataSourceCreator.createDataSource(property);
-            dataSource.addDataSource(newDsName, currDs);
+            dataSource.addDataSource(newSchema, currDs);
         }
         // 设置当前数据源
-        DynamicDataSourceContextHolder.push(newDsName);
+        DynamicDataSourceContextHolder.push(newSchema);
+    }
+
+    /**
+     * 获取新实例名
+     * @param defaultSchema
+     * @return 初始实例名_集团编码
+     */
+    private String getNewSchema(String defaultSchema) {
+        String groupCode = AppContext.getContext().getGroupCode();
+        // 当默认实例名或集团编码为空时,切换到默认数据源
+        if(StrUtil.isBlank(defaultSchema) || StrUtil.isBlank(groupCode)) {
+            return defaultProperty.getPrimary();
+        }
+        // 拼接groupCode
+        String newSchema = defaultSchema + "_" + groupCode;
+        // 转小写
+        return newSchema.toLowerCase();
+    }
+
+    /**
+     * 获取默认实例名
+     * @return
+     */
+    private String getPrimarySchema() {
+        // 取默认数据源
+        DataSourceProperty srcProperty = defaultProperty.getDatasource().get(defaultProperty.getPrimary());
+        String url = srcProperty.getUrl();
+        // 截取最后一个/到?之间的内容即为schema
+        int startIndex = StrUtil.lastIndexOfIgnoreCase(url, "/");
+        int endIndex = StrUtil.indexOfIgnoreCase(url, "?");
+        if(startIndex <= 0 || endIndex <= startIndex) {
+            return null;
+        }
+        // 没有?时截取到最后
+        return StrUtil.sub(url, startIndex + 1, endIndex);
     }
 
     /**
      * 复制新的数据源
-     * @param dbNameDefault 默认连接的实例名
-     * @param newDsName 新创建的实例名
+     * @param defaultSchema 默认连接的实例名
+     * @param newSchema 新创建的实例名
      * @return
      */
-    private DataSourceProperty copyProperty(String dbNameDefault, String newDsName) {
+    private DataSourceProperty copyProperty(String defaultSchema, String newSchema) {
         // 取默认数据源
         DataSourceProperty srcProperty = defaultProperty.getDatasource().get(defaultProperty.getPrimary());
         // 设置新数据源
         DataSourceProperty property = new DataSourceProperty();
         BeanUtils.copyProperties(srcProperty, property);
-        property.setPoolName(newDsName);
-        property.setUrl(StrUtil.replace(property.getUrl(), dbNameDefault, newDsName));
+        property.setPoolName(newSchema);
+        property.setUrl(StrUtil.replace(property.getUrl(), defaultSchema, newSchema));
         return property;
     }
 }

+ 1 - 0
dmp-comp/dmp-mybatis/src/main/java/com/persagy/dmp/mybatis/helper/DynamicDataSourceHelper.java

@@ -12,6 +12,7 @@ public class DynamicDataSourceHelper {
 
     /**
      * 切换数据源
+     * 注意:要在事务开启前执行,在事务内部执行此方法数据源不会切换
      */
     public static void loadDataSource() {
         SpringHelper.getBean(DynamicDataSourceHandler.class).resetDataSource();