DbSyncController.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. package jnpf.base.controller;
  2. import cn.dev33.satoken.annotation.SaCheckPermission;
  3. import com.alibaba.fastjson.JSONObject;
  4. import com.google.common.collect.ImmutableMap;
  5. import io.swagger.v3.oas.annotations.tags.Tag;
  6. import io.swagger.v3.oas.annotations.Parameter;
  7. import io.swagger.v3.oas.annotations.Parameters;
  8. import io.swagger.v3.oas.annotations.Operation;
  9. import jnpf.base.ActionResult;
  10. import jnpf.base.model.dbsync.DbSyncForm;
  11. import jnpf.base.model.dbsync.DbSyncPrintForm;
  12. import jnpf.base.model.dbsync.DbSyncVo;
  13. import jnpf.base.service.DbLinkService;
  14. import jnpf.base.service.DbSyncService;
  15. import jnpf.base.service.DbTableService;
  16. import jnpf.constant.MsgCode;
  17. import jnpf.database.datatype.db.interfaces.DtInterface;
  18. import jnpf.database.datatype.sync.util.DtSyncUtil;
  19. import jnpf.database.model.dbfield.DbFieldModel;
  20. import jnpf.database.model.dto.PrepSqlDTO;
  21. import jnpf.database.model.entity.DbLinkEntity;
  22. import jnpf.database.source.impl.DbOracle;
  23. import jnpf.database.sql.model.SqlPrintHandler;
  24. import jnpf.database.sql.param.FormatSqlOracle;
  25. import jnpf.database.sql.util.SqlFastUtil;
  26. import jnpf.database.util.DataSourceUtil;
  27. import jnpf.util.XSSEscape;
  28. import lombok.Cleanup;
  29. import org.springframework.beans.factory.annotation.Autowired;
  30. import org.springframework.web.bind.annotation.*;
  31. import java.io.File;
  32. import java.sql.Connection;
  33. import java.util.*;
  34. /**
  35. * 数据同步
  36. *
  37. * @author JNPF开发平台组
  38. * @version V3.1.0
  39. * @copyright 引迈信息技术有限公司
  40. * @date 2019年9月27日 上午9:18
  41. */
  42. @Tag(name = "数据同步", description = "DataSync")
  43. @RestController
  44. @RequestMapping("/api/system/DataSync")
  45. public class DbSyncController {
  46. @Autowired
  47. private DbSyncService dbSyncService;
  48. @Autowired
  49. private DbLinkService dblinkService;
  50. @Autowired
  51. private DbTableService dbTableService;
  52. @Autowired
  53. private SqlPrintHandler sqlPrintHandler;
  54. @Autowired
  55. private DataSourceUtil dataSourceUtil;
  56. /**
  57. * 验证连接
  58. *
  59. * @param dbSyncForm 页面参数
  60. * @return
  61. * @throws Exception
  62. */
  63. @PostMapping("Actions/checkDbLink")
  64. @Parameters({
  65. @Parameter(name = "dbSyncForm", description = "页面参数", required = true)
  66. })
  67. @SaCheckPermission("systemData.dataSync")
  68. @Operation(summary = "验证连接")
  69. public ActionResult<DbSyncVo> checkDbLink(@RequestBody DbSyncForm dbSyncForm) throws Exception {
  70. String fromDbType;
  71. String toDbType;
  72. DbSyncVo vo = new DbSyncVo();
  73. try {
  74. DbLinkEntity dbLinkEntity = dblinkService.getResource(dbSyncForm.getDbConnectionFrom());
  75. DbLinkEntity dbLinkEntity1 = dblinkService.getResource(dbSyncForm.getDbConnectionTo());
  76. fromDbType = dbLinkEntity.getDbType();
  77. toDbType = dbLinkEntity1.getDbType();
  78. @Cleanup Connection conn = PrepSqlDTO.getConn(dbLinkEntity);
  79. @Cleanup Connection conn1 = PrepSqlDTO.getConn(dbLinkEntity1);
  80. if (conn.getMetaData().getURL().equals(conn1.getMetaData().getURL())) {
  81. return ActionResult.fail(MsgCode.SYS011.get());
  82. }
  83. vo.setCheckDbFlag(true);
  84. vo.setTableList(SqlFastUtil.getTableList(dbLinkEntity, null));
  85. // 字段类型全部对应关系
  86. Map<String, List<String>> ruleMap = getConvertRules(fromDbType, toDbType).getData();
  87. Map<String, String> defaultRuleMap = getDefaultRules(fromDbType, toDbType).getData();
  88. // 默认类型置顶
  89. for (String key : defaultRuleMap.keySet()) {
  90. List<String> list = ruleMap.get(key);
  91. if(list != null){
  92. String rule = defaultRuleMap.get(key);
  93. list.remove(rule);
  94. list.add(0, rule + " (默认)");
  95. ruleMap.put(key, list);
  96. }
  97. }
  98. vo.setConvertRuleMap(ruleMap);
  99. }catch (Exception e){
  100. return ActionResult.fail(MsgCode.DB302.get());
  101. }
  102. return ActionResult.success(vo);
  103. }
  104. /**
  105. * 执行数据同步
  106. *
  107. * @param dbSyncForm 数据同步参数
  108. * @return ignore
  109. * @throws Exception ignore
  110. */
  111. @PostMapping
  112. @Operation(summary = "数据同步校验")
  113. @Parameters({
  114. @Parameter(name = "dbSyncForm", description = "页面参数", required = true)
  115. })
  116. @SaCheckPermission("systemData.dataSync")
  117. public ActionResult<Object> checkExecute(@RequestBody DbSyncForm dbSyncForm) throws Exception {
  118. int status;
  119. try {
  120. status = dbSyncService.executeCheck(dbSyncForm.getDbConnectionFrom(), dbSyncForm.getDbConnectionTo(), dbSyncForm.getConvertRuleMap(), dbSyncForm.getDbTable());
  121. } catch (Exception e) {
  122. e.printStackTrace();
  123. return ActionResult.fail(e.getMessage());
  124. }
  125. if (status == -1) {
  126. return ActionResult.fail(MsgCode.SYS012.get());
  127. }
  128. return ActionResult.success(status);
  129. }
  130. /**
  131. * 执行数据同步
  132. *
  133. * @param dbSyncForm 数据同步参数
  134. * @return ignore
  135. * @throws Exception ignore
  136. */
  137. @PostMapping("Actions/Execute")
  138. @Operation(summary = "执行数据同步")
  139. @Parameters({
  140. @Parameter(name = "dbSyncForm", description = "页面参数", required = true)
  141. })
  142. @SaCheckPermission("systemData.dataSync")
  143. public ActionResult<String> execute(@RequestBody DbSyncForm dbSyncForm) {
  144. try{
  145. dbSyncService.execute(dbSyncForm.getDbConnectionFrom(), dbSyncForm.getDbConnectionTo(), dbSyncForm.getConvertRuleMap(), dbSyncForm.getDbTable());
  146. }catch (Exception e){
  147. e.printStackTrace();
  148. return ActionResult.fail(MsgCode.SYS013.get(e.getMessage()));
  149. }
  150. return ActionResult.success(MsgCode.SU005.get());
  151. }
  152. /**
  153. * 批量执行数据同步
  154. *
  155. * @param dbSyncForm 数据同步参数
  156. * @return ignore
  157. * @throws Exception ignore
  158. */
  159. @PostMapping("Actions/batchExecute")
  160. @Operation(summary = "批量执行数据同步")
  161. @Parameters({
  162. @Parameter(name = "dbSyncForm", description = "页面参数", required = true)
  163. })
  164. @SaCheckPermission("systemData.dataSync")
  165. public ActionResult<Map<String, Integer>> executeBatch(@RequestBody DbSyncForm dbSyncForm) {
  166. Map<String, Integer> result = dbSyncService.executeBatch(dbSyncForm.getDbConnectionFrom(), dbSyncForm.getDbConnectionTo(), dbSyncForm.getConvertRuleMap(), dbSyncForm.getDbTableList());
  167. return ActionResult.success(MsgCode.SU005.get(), result);
  168. }
  169. /**
  170. * 获取数据类型默认转换规则
  171. * 一对一
  172. * @param fromDbType 被转换数据库类型
  173. * @param toDbType 转换数据库类型
  174. * @return 转换规则
  175. * @throws Exception 未找到数库
  176. */
  177. @GetMapping("Actions/getDefaultRules")
  178. @SaCheckPermission("systemData.dataSync")
  179. @Operation(summary = "获取一对一数据类型默认转换规则")
  180. public static ActionResult<Map<String, String>> getDefaultRules(String fromDbType, String toDbType) throws Exception{
  181. Map<String, String> map = new LinkedHashMap<>();
  182. for (DtInterface dtInterface : DtInterface.getClz(fromDbType).getEnumConstants()) {
  183. DtInterface toFixCovert = DtSyncUtil.getToFixCovert(dtInterface, toDbType);
  184. if(toFixCovert != null){
  185. map.put(dtInterface.getDataType(), toFixCovert.getDataType());
  186. }
  187. }
  188. return ActionResult.success(map);
  189. }
  190. /**
  191. * 获取数据类型转换规则
  192. * 一对多
  193. * @param fromDbType 被转换数据库类型
  194. * @param toDbType 转换数据库类型
  195. * @return 转换规则
  196. * @throws Exception 未找到数库
  197. */
  198. @GetMapping("Actions/getConvertRules")
  199. @SaCheckPermission("systemData.dataSync")
  200. @Operation(summary = "获取一对多数据类型转换规则")
  201. public static ActionResult<Map<String, List<String>>> getConvertRules(String fromDbType, String toDbType) throws Exception{
  202. Map<String, List<String>> map = new LinkedHashMap<>();
  203. for (DtInterface dtInterface : DtInterface.getClz(fromDbType).getEnumConstants()) {
  204. List<String> list = new LinkedList<>();
  205. DtInterface[] allConverts = DtSyncUtil.getAllConverts(dtInterface, toDbType);
  206. if(allConverts != null){
  207. for (DtInterface allConvert : allConverts) {
  208. list.add(allConvert.getDataType());
  209. }
  210. map.put(dtInterface.getDataType(), list);
  211. }
  212. }
  213. return ActionResult.success(map);
  214. }
  215. /* ===================================== SQL转换项目 ======================================= */
  216. /**
  217. * 打印转换SQL
  218. *
  219. * @param form 参数表单
  220. */
  221. @PostMapping("Actions/print")
  222. @Operation(summary = "打印同步表")
  223. public ActionResult<Object> print(@RequestBody DbSyncPrintForm form) throws Exception{
  224. PrintFunction func = ()-> dbSyncService.printDbInit(form.getDbLinkFrom(), form.getDbTypeTo(),
  225. form.getDbTableList(), form.getConvertRuleMap(), form.getPrintType());
  226. return ActionResult.success(printCommon(form, form.getPrintType(), func));
  227. }
  228. @FunctionalInterface
  229. public interface PrintFunction {
  230. Object execute() throws Exception;
  231. }
  232. private Object printCommon(DbSyncPrintForm form, String printType, PrintFunction func) throws Exception {
  233. String filePath = XSSEscape.escapePath(form.getOutPath());
  234. sqlPrintHandler.start(filePath, true, true, true, form.getDbTypeTo());
  235. sqlPrintHandler.setFileName(form.getOutFileName());
  236. Object obj = func.execute();
  237. sqlPrintHandler.print();
  238. sqlPrintHandler.close();
  239. // SqlPrintHandler.openDirectory(new File(filePath).getPath());
  240. return obj;
  241. }
  242. /**
  243. * 数据类型转换
  244. *
  245. * @param dataType 数据类型 例如:varchar(50)
  246. * @param fromDbEncode 源数据库类型
  247. * @param toDbEncode 目标数据库类型
  248. */
  249. @GetMapping("getConvertDataType")
  250. @Operation(summary = "数据类型转换")
  251. public String getConvertDataType(String dataType, String dtLength, String fromDbEncode, String toDbEncode) throws Exception{
  252. DbFieldModel dbFieldModel = new DbFieldModel();
  253. dbFieldModel.setLength(dtLength);
  254. DtInterface toFixCovert = DtSyncUtil.getToFixCovert(DtInterface.newInstanceByDt(dataType, fromDbEncode), toDbEncode);
  255. dbFieldModel.setDataType(toFixCovert.getDataType());
  256. return dbFieldModel.formatDataTypeByView(toDbEncode);
  257. }
  258. @PostMapping("formatOracleValue")
  259. @Operation(summary = "格式化SQL语句中的Oracle值")
  260. public String getConvertDataType(@RequestBody String data) throws Exception{
  261. Map<String, Object> json = JSONObject.parseObject(data).getInnerMap();
  262. // 指定F_Id为主键
  263. Map<String, Object> dataMap = JSONObject.parseObject(json.get("dataMap").toString()).getInnerMap();
  264. // 特殊处理:存在值超过2000的字符
  265. StringBuilder valStrBuilder = new StringBuilder();
  266. String context = FormatSqlOracle.clobExecute(DbOracle.ORACLE, json.get("valueStr"),
  267. json.get("table").toString(), json.get("column").toString(), dataMap, valStrBuilder).toString();
  268. return valStrBuilder.toString();
  269. }
  270. }