DataMigrationTest.java 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. import com.alibaba.druid.pool.DruidDataSource;
  2. import com.gccloud.common.utils.JSON;
  3. import com.google.common.collect.Lists;
  4. import com.google.common.collect.Maps;
  5. import lombok.extern.slf4j.Slf4j;
  6. import org.apache.commons.lang3.StringUtils;
  7. import org.json.JSONArray;
  8. import org.json.JSONObject;
  9. import org.junit.Test;
  10. import org.junit.runner.RunWith;
  11. import org.springframework.jdbc.core.JdbcTemplate;
  12. import org.springframework.test.context.junit4.SpringRunner;
  13. import java.util.List;
  14. import java.util.Map;
  15. import java.util.Set;
  16. import java.util.stream.Collectors;
  17. /**
  18. * @author hongyang
  19. * @version 1.0
  20. * @date 2023/6/20 15:29
  21. */
  22. @Slf4j
  23. @RunWith(SpringRunner.class)
  24. public class DataMigrationTest {
  25. /**
  26. * 版本升级处理数据集数据迁移
  27. * 执行前请:
  28. * 1. 执行doc/update.sql
  29. * 2. 修改数据库连接信息
  30. */
  31. @Test
  32. public void dataMigration() {
  33. // 设置数据源
  34. DruidDataSource dataSource = new DruidDataSource();
  35. dataSource.setDriverClassName("com.mysql.jdbc.Driver");
  36. dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/dataroom?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=UTF-8");
  37. dataSource.setUsername("root");
  38. dataSource.setPassword("pwd");
  39. JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
  40. // 处理数据源
  41. log.info("开始处理数据源");
  42. handleDataSource(jdbcTemplate);
  43. // 处理分类
  44. log.info("开始处理分类");
  45. handleCategory(jdbcTemplate);
  46. // 处理数据集
  47. log.info("开始处理数据集");
  48. handleDataset(jdbcTemplate);
  49. }
  50. /**
  51. * 数据源数据迁移
  52. * @param jdbcTemplate
  53. */
  54. private static void handleDataSource(JdbcTemplate jdbcTemplate) {
  55. String migrateSql = "INSERT INTO ds_datasource (id, source_name, source_type, driver_class_name, url, host, port, username, password, module_code, editable, remark, update_date, create_date, del_flag)\n" +
  56. "SELECT id, source_name, source_type, driver_class_name, url, host, port, username, password, module_code, editable, remark, update_date, create_date, del_flag\n" +
  57. "FROM big_screen_datasource_config where del_flag = 0";
  58. jdbcTemplate.execute(migrateSql);
  59. String updateSql = "UPDATE ds_datasource SET source_type = 'PostgreSQL' where source_type = 'TelePG'";
  60. jdbcTemplate.execute(updateSql);
  61. String updateSql2 = "UPDATE ds_datasource SET source_type = 'Mysql' where source_type = 'TeleDB'";
  62. jdbcTemplate.execute(updateSql2);
  63. log.info("数据源数据迁移完成");
  64. }
  65. /**
  66. * 分类树ids更新SQL
  67. */
  68. public static final String updateSql = "update ds_category_tree set ids = '%s' where id = '%s'";
  69. /**
  70. * 分类树数据迁移
  71. * @param jdbcTemplate
  72. */
  73. private static void handleCategory(JdbcTemplate jdbcTemplate) {
  74. String migrateSql = "INSERT INTO ds_category_tree (id, name, parent_id, type, module_code, update_date, create_date, del_flag)\n" +
  75. "SELECT id, name, parent_id, table_name, module_code, update_date, create_date, del_flag\n" +
  76. "FROM big_screen_category_tree where del_flag = 0";
  77. jdbcTemplate.execute(migrateSql);
  78. String sql = "select * from ds_category_tree where del_flag = 0";
  79. List<Map<String, Object>> categoryList = jdbcTemplate.queryForList(sql);
  80. // 根据parent_id组装成树形结构,将子节点放到父节点的children中,并组装ids
  81. Map<String, Map<String, Object>> categoryMap = Maps.newHashMap();
  82. categoryList.forEach(category -> categoryMap.put(category.get("id").toString(), category));
  83. categoryList.forEach(category -> {
  84. String parentId = category.get("parent_id").toString();
  85. if (StringUtils.isBlank(parentId) || "0".equals(parentId)) {
  86. return;
  87. }
  88. Map<String, Object> parentCategory = categoryMap.get(parentId);
  89. if (parentCategory == null) {
  90. return;
  91. }
  92. List<Map<String, Object>> children = (List<Map<String, Object>>) parentCategory.get("children");
  93. if (children == null) {
  94. children = Lists.newArrayList();
  95. parentCategory.put("children", children);
  96. }
  97. children.add(category);
  98. });
  99. // 取出根节点
  100. List<Map<String, Object>> rootCategoryList = categoryList.stream().filter(category -> {
  101. String parentId = category.get("parent_id").toString();
  102. return StringUtils.isBlank(parentId) || "0".equals(parentId);
  103. }).collect(Collectors.toList());
  104. // 处理ids
  105. handleIds(rootCategoryList, "");
  106. List<String> updateSqlList = Lists.newArrayList();
  107. // 类型修改
  108. updateSqlList.add("update ds_category_tree set type = 'dataset' where type = 'r_dataset'");
  109. // 组装update sql
  110. getUpdateSql(rootCategoryList, updateSqlList);
  111. // 批量执行update sql
  112. jdbcTemplate.batchUpdate(updateSqlList.toArray(new String[0]));
  113. log.info("分类树数据迁移完成");
  114. }
  115. /**
  116. * 处理分类树ids
  117. * @param categoryList
  118. * @param parentIds
  119. */
  120. private static void handleIds(List<Map<String, Object>> categoryList, String parentIds) {
  121. if (categoryList == null || categoryList.isEmpty()) {
  122. return;
  123. }
  124. categoryList.forEach(category -> {
  125. String id = category.get("id").toString();
  126. String ids = parentIds + "," + id;
  127. if (StringUtils.isBlank(parentIds)) {
  128. ids = id;
  129. }
  130. category.put("ids", ids);
  131. List<Map<String, Object>> children = (List<Map<String, Object>>) category.get("children");
  132. handleIds(children, ids);
  133. });
  134. }
  135. /**
  136. * 组装分类树update sql
  137. * @param categoryList
  138. * @param updateSqlList
  139. */
  140. private static void getUpdateSql(List<Map<String, Object>> categoryList, List<String> updateSqlList) {
  141. if (categoryList == null || categoryList.isEmpty()) {
  142. return;
  143. }
  144. categoryList.forEach(category -> {
  145. String id = category.get("id").toString();
  146. String ids = category.get("ids").toString();
  147. updateSqlList.add(String.format(updateSql, ids, id));
  148. List<Map<String, Object>> children = (List<Map<String, Object>>) category.get("children");
  149. getUpdateSql(children, updateSqlList);
  150. });
  151. }
  152. /**
  153. * 数据集新增SQL
  154. */
  155. public static final String insertSql = "INSERT INTO ds_dataset (id, name, code, type_id, remark, dataset_type, module_code, editable, source_id, cache, config) VALUES ('%s', '%s', '%s', %s, '%s', '%s', '%s', %s, %s, %s, '%s');";
  156. /**
  157. * 数据集数据迁移
  158. * @param jdbcTemplate
  159. */
  160. private static void handleDataset(JdbcTemplate jdbcTemplate) {
  161. // 新增SQL集合
  162. List<String> insertSqlList = Lists.newArrayList();
  163. // 处理JSON类型的数据集
  164. String sql = "select * from big_screen_dataset where dataset_type = 'json' and del_flag = 0";
  165. List<Map<String, Object>> jsonDatasetList = jdbcTemplate.queryForList(sql);
  166. for (Map<String, Object> dataset : jsonDatasetList) {
  167. String data = dataset.get("data").toString();
  168. // 解析data
  169. JSONObject dataJson = JSON.parseObject(data);
  170. Object json = dataJson.get("json");
  171. JSONObject fieldDesc = dataJson.getJSONObject("fieldDesc");
  172. // 遍历fieldDesc,取出key和value
  173. Set<String> keySet = fieldDesc.keySet();
  174. List<Map<String, Object>> fieldList = Lists.newArrayList();
  175. for (String key : keySet) {
  176. Object value = fieldDesc.get(key);
  177. Map<String, Object> fieldMap = Maps.newHashMap();
  178. fieldMap.put("fieldName", key);
  179. fieldMap.put("fieldDesc", value);
  180. fieldList.add(fieldMap);
  181. }
  182. JSONObject jsonConfig = new JSONObject();
  183. jsonConfig.put("fieldList", fieldList);
  184. String jsonStr = JSON.toJSONString(json);
  185. jsonConfig.put("json", escape(jsonStr));
  186. jsonConfig.put("fieldDesc", fieldDesc);
  187. jsonConfig.put("className", "com.gccloud.dataset.entity.config.JsonDataSetConfig");
  188. String config = JSON.toJSONString(jsonConfig);
  189. String insertSql = getInsertSql(dataset, config);
  190. insertSqlList.add(insertSql);
  191. }
  192. // 处理script类型的数据集
  193. sql = "select * from big_screen_dataset where dataset_type = 'script' and del_flag = 0";
  194. List<Map<String, Object>> scriptDatasetList = jdbcTemplate.queryForList(sql);
  195. for (Map<String, Object> dataset : scriptDatasetList) {
  196. String data = dataset.get("data").toString();
  197. // 解析data
  198. JSONObject dataJson = JSON.parseObject(data);
  199. Object script = dataJson.get("script");
  200. Object paramsList = dataJson.get("paramsList");
  201. JSONObject fieldDesc = dataJson.getJSONObject("fieldDesc");
  202. // 遍历fieldDesc,取出key和value
  203. Set<String> keySet = fieldDesc.keySet();
  204. List<Map<String, Object>> fieldList = Lists.newArrayList();
  205. for (String key : keySet) {
  206. Object value = fieldDesc.get(key);
  207. Map<String, Object> fieldMap = Maps.newHashMap();
  208. fieldMap.put("fieldName", key);
  209. fieldMap.put("fieldDesc", value);
  210. fieldList.add(fieldMap);
  211. }
  212. JSONObject jsonConfig = new JSONObject();
  213. jsonConfig.put("fieldList", fieldList);
  214. jsonConfig.put("script", escape(script.toString()));
  215. jsonConfig.put("paramsList", paramsList);
  216. jsonConfig.put("fieldDesc", fieldDesc);
  217. jsonConfig.put("className", "com.gccloud.dataset.entity.config.GroovyDataSetConfig");
  218. String config = JSON.toJSONString(jsonConfig);
  219. String insertSql = getInsertSql(dataset, config);
  220. insertSqlList.add(insertSql);
  221. }
  222. // 处理original类型的数据集
  223. sql = "select a.*,b.* from big_screen_dataset a left join big_screen_datasets_original b on a.dataset_rel_id = b.id where a.dataset_rel_id is not null and a.dataset_type = 'original' and a.del_flag = 0 and b.del_flag =0";
  224. List<Map<String, Object>> originalDatasetList = jdbcTemplate.queryForList(sql);
  225. for (Map<String, Object> dataset : originalDatasetList) {
  226. String sourceId = dataset.get("source_id").toString();
  227. String tableName = dataset.get("table_name").toString();
  228. Object repeatStatus = dataset.get("repeat_status");
  229. Object fieldDesc = dataset.get("field_desc");
  230. JSONObject fieldDescObj = JSON.parseObject(fieldDesc.toString());
  231. String fieldInfo = dataset.get("field_info").toString();
  232. JSONArray fieldJson = JSON.parseArray(dataset.get("field_json").toString());
  233. List<Map<String, Object>> fieldList = Lists.newArrayList();
  234. fieldJson.toList().forEach(field -> {
  235. Map<String, Object> fieldMap = Maps.newHashMap();
  236. fieldMap.put("fieldName", ((Map) field).get("columnName"));
  237. fieldMap.put("fieldType", ((Map) field).get("columnType"));
  238. fieldMap.put("orderNum", ((Map) field).get("orderNum"));
  239. fieldMap.put("sourceTable", ((Map) field).get("sourceTable"));
  240. fieldMap.put("fieldDesc", ((Map) field).get("fieldDesc"));
  241. fieldList.add(fieldMap);
  242. });
  243. JSONObject jsonConfig = new JSONObject();
  244. jsonConfig.put("sourceId", sourceId);
  245. jsonConfig.put("tableName", tableName);
  246. jsonConfig.put("repeatStatus", repeatStatus);
  247. jsonConfig.put("fieldDesc", fieldDescObj);
  248. jsonConfig.put("fieldInfo", fieldInfo);
  249. jsonConfig.put("fieldList", fieldList);
  250. jsonConfig.put("className", "com.gccloud.dataset.entity.config.OriginalDataSetConfig");
  251. String config = JSON.toJSONString(jsonConfig);
  252. String insertSql = getInsertSql(dataset, config);
  253. insertSqlList.add(insertSql);
  254. }
  255. // 处理custom、storedProcedure类型的数据集
  256. sql = "select a.*, b.*\n" +
  257. "from big_screen_dataset a\n" +
  258. " left join big_screen_datasets_custom b on a.dataset_rel_id = b.id\n" +
  259. "where a.dataset_rel_id is not null\n" +
  260. " and ( a.dataset_type = 'storedProcedure' or a.dataset_type = 'custom')\n" +
  261. " and a.del_flag = 0\n" +
  262. " and b.del_flag = 0\n";
  263. List<Map<String, Object>> customDatasetList = jdbcTemplate.queryForList(sql);
  264. for (Map<String, Object> dataset : customDatasetList) {
  265. String sourceId = dataset.get("source_id").toString();
  266. String sqlProcess = dataset.get("sql_process").toString();
  267. Object fieldDesc = dataset.get("field_desc");
  268. JSONObject fieldDescObj = JSON.parseObject(fieldDesc.toString());
  269. Object paramList = dataset.get("param_config");
  270. JSONArray fieldJson = JSON.parseArray(dataset.get("field_json").toString());
  271. List<Map<String, Object>> fieldList = Lists.newArrayList();
  272. fieldJson.toList().forEach(field -> {
  273. Map<String, Object> fieldMap = Maps.newHashMap();
  274. fieldMap.put("fieldName", ((Map) field).get("columnName"));
  275. fieldMap.put("fieldType", ((Map) field).get("columnType"));
  276. fieldMap.put("orderNum", ((Map) field).get("orderNum"));
  277. fieldMap.put("sourceTable", ((Map) field).get("sourceTable"));
  278. fieldMap.put("fieldDesc", ((Map) field).get("fieldDesc"));
  279. fieldList.add(fieldMap);
  280. });
  281. JSONObject jsonConfig = new JSONObject();
  282. jsonConfig.put("sourceId", sourceId);
  283. jsonConfig.put("sqlProcess", escape(sqlProcess));
  284. jsonConfig.put("fieldDesc", fieldDescObj);
  285. jsonConfig.put("fieldList", fieldList);
  286. JSONArray paramsList = new JSONArray();
  287. if (StringUtils.isNotBlank(paramList.toString())) {
  288. paramsList = JSON.parseArray(paramList.toString());
  289. }
  290. jsonConfig.put("paramsList", paramsList);
  291. if (dataset.get("dataset_type").toString().equals("storedProcedure")) {
  292. jsonConfig.put("className", "com.gccloud.dataset.entity.config.StoredProcedureDataSetConfig");
  293. } else {
  294. jsonConfig.put("className", "com.gccloud.dataset.entity.config.CustomDataSetConfig");
  295. }
  296. String config = JSON.toJSONString(jsonConfig);
  297. // 将 \\' 替换成 \'
  298. config = config.replaceAll("\\\\\\\\'", "\\\\'");
  299. String insertSql = getInsertSql(dataset, config);
  300. insertSqlList.add(insertSql);
  301. }
  302. // 批量新增
  303. insertSqlList.forEach(jdbcTemplate::execute);
  304. log.info("数据集配置迁移完成");
  305. }
  306. /**
  307. * 组装数据集插入sql
  308. * @param dataset
  309. * @param config
  310. * @return
  311. */
  312. private static String getInsertSql(Map<String, Object> dataset, String config) {
  313. String id = dataset.get("id").toString();
  314. String name = dataset.get("name").toString();
  315. String type_id = dataset.get("type_id") == null ? "null" : dataset.get("type_id").toString();
  316. String remark = dataset.get("remark").toString();
  317. String dataset_type = dataset.get("dataset_type").toString();
  318. String module_code = "";
  319. String editable = dataset.get("editable").toString();
  320. String source_id = dataset.get("source_id") == null ? "null" : dataset.get("source_id").toString();
  321. String code = "";
  322. String cache = "0";
  323. return String.format(insertSql, id, name, code, type_id, remark, dataset_type, module_code, editable, source_id, cache, config);
  324. }
  325. /**
  326. * 转义字符串
  327. * @param str
  328. * @return
  329. */
  330. private static String escape(String str) {
  331. str = str.replace("\\", "\\\\");
  332. str = str.replace("'", "\\'");
  333. str = str.replace("\"", "\\\"");
  334. str = str.replace("\n", "\\n");
  335. str = str.replace("\r", "\\r");
  336. str = str.replace("\t", "\\t");
  337. return str;
  338. }
  339. }