SqlFastUtil.java 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. package jnpf.database.sql.util;
  2. import jnpf.base.Pagination;
  3. import jnpf.constant.MsgCode;
  4. import jnpf.database.constant.DbAliasConst;
  5. import jnpf.database.enums.DbAliasEnum;
  6. import jnpf.database.model.dbfield.DbFieldModel;
  7. import jnpf.database.model.dbtable.DbTableFieldModel;
  8. import jnpf.database.model.dto.PrepSqlDTO;
  9. import jnpf.database.model.entity.DbLinkEntity;
  10. import jnpf.database.source.DbBase;
  11. import jnpf.database.sql.enums.SqlOracleEnum;
  12. import jnpf.database.sql.enums.base.SqlComEnum;
  13. import jnpf.database.sql.model.SqlPrintHandler;
  14. import jnpf.database.sql.param.FormatSqlOracle;
  15. import jnpf.database.sql.param.base.FormatSql;
  16. import jnpf.database.util.DbTypeUtil;
  17. import jnpf.database.util.JdbcUtil;
  18. import jnpf.database.util.NotTenantPluginHolder;
  19. import jnpf.exception.DataException;
  20. import jnpf.util.StringUtil;
  21. import jnpf.util.context.SpringContext;
  22. import lombok.extern.slf4j.Slf4j;
  23. import org.apache.commons.collections4.CollectionUtils;
  24. import org.apache.commons.lang3.StringUtils;
  25. import java.util.*;
  26. import java.util.regex.Matcher;
  27. import java.util.regex.Pattern;
  28. import java.util.stream.Collectors;
  29. /**
  30. * 常用SQL快捷使用工具
  31. *
  32. * @author JNPF开发平台组 YanYu
  33. * @version V3.3
  34. * @copyright 引迈信息技术有限公司
  35. * @date 2022-06-11
  36. */
  37. @Slf4j
  38. public class SqlFastUtil {
  39. private static SqlPrintHandler sqlPrintHandler = SpringContext.getBean(SqlPrintHandler.class);
  40. /**
  41. * 添加表
  42. */
  43. public static void creTable(DbLinkEntity dbLinkEntity, DbTableFieldModel dbTableFieldModel) throws Exception {
  44. List<DbFieldModel> dbFieldModelList = dbTableFieldModel.getDbFieldModelList();
  45. // 生成表
  46. List<String> fieldSqlList = new ArrayList<>();
  47. if(CollectionUtils.isNotEmpty(dbFieldModelList)){
  48. List<String> primaryKeys = new ArrayList<>();
  49. for(DbFieldModel fieldModel : dbFieldModelList){
  50. String fieldSql = SqlComEnum.CREATE_TABLE.getOutSqlByDb(
  51. dbLinkEntity.getDbType(),
  52. // 表
  53. "",
  54. // 字段
  55. FormatSql.getFieldName(fieldModel.getField(), dbLinkEntity.getDbType()),
  56. // 数据类型
  57. fieldModel.formatDataTypeByView(dbLinkEntity.getDbType()),
  58. // 默认值
  59. FormatSql.defaultCheck(fieldModel, dbLinkEntity.getDbType()),
  60. // 非空(默认允空NULL)
  61. fieldModel.getNullSign().equals(DbAliasConst.NOT_NULL) ? fieldModel.getNullSign() : "",
  62. // 主键
  63. //fieldModel.getIsPrimaryKey() != null && fieldModel.getIsPrimaryKey() ? "PRIMARY KEY" : "",
  64. // 自增
  65. fieldModel.getIsAutoIncrement() != null && fieldModel.getIsAutoIncrement() ? "AUTO_INCREMENT" : "",
  66. // 注释
  67. "COMMENT '" + fieldModel.getComment() + "'"
  68. );
  69. if(fieldModel.getIsPrimaryKey()){
  70. primaryKeys.add(fieldModel.getField());
  71. }
  72. Matcher matcher = Pattern.compile("【([\\s\\S]+)】").matcher(fieldSql);
  73. if (matcher.find()){
  74. String fieldSqlFragment = matcher.group(1);
  75. fieldSqlList.add("\t" + (fieldSqlFragment.replaceAll("\\s+", " ").trim()));
  76. } else {
  77. throw new DataException(MsgCode.DB015.get());
  78. }
  79. }
  80. String sql = SqlComEnum.CREATE_TABLE.getOutSqlByDb(dbLinkEntity.getDbType(),
  81. SqlFrameUtil.htmlE(dbTableFieldModel.getTable()), null, null, null, null, null, null, StringUtil.join(primaryKeys, ",")).replaceAll("【.+】", StringUtil.join(fieldSqlList, ",\n"));
  82. NotTenantPluginHolder.setNotSwitchFlag();
  83. // 打印或生成
  84. if (!sqlPrintHandler.creTable(sql)) JdbcUtil.creUpDe(new PrepSqlDTO(sql).withConn(dbLinkEntity));
  85. // ORACLE特殊自增方式
  86. FormatSqlOracle.autoIncrement(dbLinkEntity, dbTableFieldModel);
  87. }else {
  88. throw new DataException(MsgCode.DB016.get());
  89. }
  90. // 生成注释
  91. commentTable(dbLinkEntity, dbTableFieldModel.getTable(), dbTableFieldModel.getComment());
  92. if(!DbTypeUtil.checkMySQL(dbLinkEntity)){
  93. creTableCommentFiled(dbLinkEntity, dbTableFieldModel.getTable(), dbFieldModelList);
  94. }
  95. }
  96. /**
  97. * 添加字段
  98. */
  99. public static List<Boolean> addField(DbLinkEntity dbLinkEntity, String table, List<DbFieldModel> dbFieldModelList) throws Exception {
  100. // 原表字段集合
  101. List<DbFieldModel> originFieldList = getFieldList(dbLinkEntity, table);
  102. List<Boolean> existsFieldFlagList = new ArrayList<>();
  103. for (DbFieldModel dbFieldModel : dbFieldModelList) {
  104. boolean existsFieldFlag = false;
  105. // 查询表添加这个的字段是否已存在,不存在则执行添加
  106. for (DbFieldModel originFile : originFieldList) {
  107. if(originFile.getField().equalsIgnoreCase(dbFieldModel.getField())){
  108. existsFieldFlag = true;
  109. break;
  110. }
  111. }
  112. existsFieldFlagList.add(existsFieldFlag);
  113. if(existsFieldFlag){
  114. continue;
  115. }
  116. String sql = SqlComEnum.ADD_COLUMN.getOutSqlByDb(
  117. dbLinkEntity.getDbType(),
  118. "ADD",
  119. table,
  120. dbFieldModel.getField(),
  121. dbFieldModel.formatDataTypeByView(dbLinkEntity.getDbType()),
  122. dbFieldModel.getNullSign(),
  123. "",
  124. "'" + dbFieldModel.getComment() + "'"
  125. );
  126. NotTenantPluginHolder.setNotSwitchFlag();
  127. JdbcUtil.creUpDe(new PrepSqlDTO(sql).withConn(dbLinkEntity));
  128. // 字段注释
  129. if(!DbTypeUtil.checkMySQL(dbLinkEntity)){
  130. commentFiled(dbLinkEntity, table, dbFieldModel.getField(), dbFieldModel.getDataType(), dbFieldModel.getComment());
  131. }
  132. }
  133. return existsFieldFlagList;
  134. }
  135. /**
  136. * 删表
  137. */
  138. public static Boolean dropTable(DbLinkEntity dbLinkEntity, String table) throws Exception {
  139. NotTenantPluginHolder.setNotSwitchFlag();
  140. String sql = SqlComEnum.DROP_TABLE.getOutSql(SqlFrameUtil.htmlE(table));
  141. int flag = 0;
  142. if (!sqlPrintHandler.dropTable(sql)){
  143. flag = JdbcUtil.delete(new PrepSqlDTO(sql).withConn(dbLinkEntity));
  144. }
  145. return flag > 0;
  146. }
  147. /**
  148. * 表重命名
  149. */
  150. public static Boolean reTableName(DbLinkEntity dbLinkEntity, String oldTable, String newTable) throws Exception {
  151. NotTenantPluginHolder.setNotSwitchFlag();
  152. int i = JdbcUtil.creUpDe(new PrepSqlDTO(SqlComEnum.RE_TABLE_NAME.getOutSqlByDb(dbLinkEntity.getDbType(), oldTable, newTable)).withConn(dbLinkEntity));
  153. return i > 0;
  154. }
  155. /**
  156. * 表注释
  157. */
  158. public static Boolean commentTable(DbLinkEntity dbLinkEntity, String table, String comment) throws Exception {
  159. String sql = SqlComEnum.COMMENT_TABLE.getOutSqlByDb(dbLinkEntity.getDbType(), SqlFrameUtil.htmlE(table), "'" + SqlFrameUtil.htmlE(comment) + "'");
  160. NotTenantPluginHolder.setNotSwitchFlag();
  161. if (!sqlPrintHandler.comment(sql)) JdbcUtil.creUpDe(new PrepSqlDTO(sql).withConn(dbLinkEntity));
  162. return true;
  163. }
  164. /**
  165. * 批量字段注释
  166. */
  167. private static Boolean creTableCommentFiled(DbLinkEntity dbLinkEntity, String table, List<DbFieldModel> dbFieldModelList) throws Exception {
  168. String dbEncode = dbLinkEntity.getDbType();
  169. for (DbFieldModel dbFieldModel : dbFieldModelList) {
  170. String sql = SqlComEnum.COMMENT_COLUMN.getOutSqlByDb(dbEncode,
  171. table,
  172. FormatSql.getFieldName(dbFieldModel.getField(), dbEncode),
  173. "'" + dbFieldModel.getComment() + "'",
  174. dbFieldModel.formatDataTypeByView(dbEncode),
  175. null);
  176. if (!sqlPrintHandler.comment(sql)) JdbcUtil.update(new PrepSqlDTO(sql).withConn(dbLinkEntity));
  177. }
  178. return true;
  179. }
  180. /**
  181. * 字段注释
  182. */
  183. public static Boolean commentFiled(DbLinkEntity dbLinkEntity, String table, String column, String dataType, String comment) throws Exception {
  184. String sql = SqlComEnum.COMMENT_COLUMN.getOutSqlByDb(dbLinkEntity.getDbType(), table, column, "'" + comment + "'", dataType, null);
  185. NotTenantPluginHolder.setNotSwitchFlag();
  186. int i = JdbcUtil.creUpDe(new PrepSqlDTO(sql).withConn(dbLinkEntity));
  187. return i > 0;
  188. }
  189. /**
  190. * 获取分页SQL语句
  191. * @param selectSql 查询SQL语句
  192. * @param orderColumn 排序字段
  193. * @param orderSign
  194. * ASC(ascend):升序 1234 放空默认
  195. * DESC(descend):降序 4321batchInsert
  196. * @param currentPage 当前页
  197. * @param pageSize 页面大小
  198. * @return String[] 0:分页查询语句 1:统计条数语句
  199. */
  200. public static String[] getPageSql(String dbEncode, String selectSql, String orderColumn, String orderSign, Integer currentPage, Integer pageSize) throws DataException{
  201. // 排序
  202. if(StringUtil.isEmpty(orderColumn)) throw new DataException("分页查询缺少排序字段");
  203. orderSign = StringUtil.isEmpty(orderSign) ? "" : orderSign;
  204. // 起始下标
  205. String beginIndex = Integer.toString((currentPage - 1) * pageSize);
  206. // 结束下标
  207. String endIndex = Integer.toString(currentPage * pageSize);
  208. return new String[]{
  209. SqlComEnum.ORDER_PAGE.getOutSqlByDb(dbEncode, selectSql, orderColumn, beginIndex, endIndex, pageSize.toString(), orderSign),
  210. SqlComEnum.COUNT_SIZE.getOutSqlByDb(dbEncode, DbAliasEnum.TOTAL_RECORD.getAlias(dbEncode), selectSql)
  211. };
  212. }
  213. public static String[] getPageSql(String dbEncode, String selectSql, Pagination pagination) throws DataException{
  214. return getPageSql(dbEncode, selectSql,
  215. pagination.getSidx(),
  216. pagination.getSort(),
  217. Long.valueOf(pagination.getCurrentPage()).intValue(),
  218. Long.valueOf(pagination.getPageSize()).intValue());
  219. }
  220. /**
  221. * 批量添加
  222. */
  223. public static void batchInsert(String table, DbLinkEntity dbLinkEntity, List<Map<String, Object>> multiDataMapList) throws Exception {
  224. // 表数据清空语句打印
  225. if(sqlPrintHandler.getPrintFlag()){
  226. if(multiDataMapList.size() > 0) sqlPrintHandler.deleteAllInfo(SqlComEnum.DELETE_ALL.getOutSqlByDb(dbLinkEntity.getDbType(), table));
  227. }
  228. int total = multiDataMapList.size();
  229. int start = 1;
  230. for (Map<String, Object> dataMap : multiDataMapList) {
  231. if(total > 100){
  232. log.info("表:" + table + "_数据:(" + start + "/" + total + ")");
  233. start++;
  234. }
  235. insert(dbLinkEntity, table, dataMap);
  236. }
  237. }
  238. /**
  239. * 单条插入
  240. */
  241. public static void insert(DbLinkEntity dbLinkEntity, String table, Map<String, Object> dataMap) throws Exception {
  242. String dbEncode = dbLinkEntity.getDbType();
  243. // 插入语句打印
  244. if(sqlPrintHandler.getPrintFlag()){
  245. sqlPrintHandler.insert(formatInsertSql(dataMap, table, dbEncode));
  246. }else {
  247. List<String> formatFieldList = new ArrayList<>();
  248. List<String> signList = new ArrayList<>();
  249. List<Object> valueList = new ArrayList<>();
  250. for (Map.Entry<String, Object> map : dataMap.entrySet()) {
  251. signList.add("?");
  252. valueList.add(map.getValue());
  253. formatFieldList.add(FormatSql.getFieldName(map.getKey(), dbEncode));
  254. }
  255. PrepSqlDTO prepSqlDTO = new PrepSqlDTO(SqlComEnum.INSERT.getOutSqlByDb(dbEncode, table,
  256. String.join(",", formatFieldList), String.join(",", signList)), valueList).withConn(dbLinkEntity);
  257. JdbcUtil.insert(prepSqlDTO);
  258. }
  259. }
  260. private static String formatInsertSql(Map<String, Object> dataMap, String table, String dbEncode) {
  261. List<String> fieldList = new ArrayList<>();
  262. List<String> valueList = new ArrayList<>();
  263. StringBuilder oracleClobUpdate = new StringBuilder();
  264. for (Map.Entry<String, Object> field : dataMap.entrySet()) {
  265. String column = field.getKey();
  266. Object columnValue = field.getValue();
  267. // 特殊处理:存在值超过2000的字符
  268. columnValue = FormatSqlOracle.clobExecute(dbEncode, columnValue, table, field.getKey(), dataMap, oracleClobUpdate);
  269. columnValue = FormatSqlOracle.blobExecute(dbEncode, columnValue, table, field.getKey(), dataMap, oracleClobUpdate);
  270. fieldList.add(FormatSql.getFieldName(column, dbEncode)); // 字段处理
  271. valueList.add(FormatSql.formatValue(columnValue, dbEncode)); // 值处理
  272. }
  273. return SqlComEnum.INSERT.getOutSqlByDb(dbEncode, table, String.join(",", fieldList), String.join(",", valueList))
  274. + ";\n" + (StringUtils.isNotEmpty(oracleClobUpdate) ? oracleClobUpdate.toString() : "");
  275. }
  276. /**
  277. * 模糊查询
  278. */
  279. public static String getFuzzyQuerySql(String selectSql, String column, String keyWord) throws DataException {
  280. if (StringUtil.isNotEmpty(keyWord)) {
  281. return SqlComEnum.LIKE.getOutSql(selectSql, column, "%" + keyWord + "%");
  282. }
  283. return selectSql;
  284. }
  285. /**
  286. * 判断表数据存在
  287. */
  288. public static Boolean tableDataExist(String dbLinkId, String table) throws Exception {
  289. DbLinkEntity dbLinkEntity = PrepSqlDTO.DB_LINK_FUN.apply(dbLinkId);
  290. String sql = SqlComEnum.COUNT_SIZE_TABLE.getOutSqlByDb(dbLinkEntity.getDbType(),"F_COUNT", table);
  291. NotTenantPluginHolder.setNotSwitchFlag();
  292. return JdbcUtil.queryOneInt(new PrepSqlDTO(sql).withConn(dbLinkId),"F_COUNT") > 0;
  293. }
  294. /**
  295. * 统计表数据行数
  296. */
  297. public static int getSum(DbLinkEntity dbLinkEntity, String table) throws Exception {
  298. PrepSqlDTO dto = new PrepSqlDTO(SqlComEnum.COUNT_SIZE.getOutSql("COUNT_SUM", "SELECT * FROM " + FormatSql.getFieldName(table, dbLinkEntity.getDbType()))).withConn(dbLinkEntity);
  299. NotTenantPluginHolder.setNotSwitchFlag();
  300. return JdbcUtil.queryOneInt(dto, "COUNT_SUM");
  301. }
  302. public static List<DbFieldModel> getFieldList(DbLinkEntity dbLinkEntity, String table) throws Exception {
  303. NotTenantPluginHolder.setNotSwitchFlag();
  304. return JdbcUtil.queryCustomMods(
  305. SqlComEnum.FIELDS.getPrepSqlDto(dbLinkEntity, table),
  306. DbFieldModel.class);
  307. }
  308. public static boolean isExistTable(DbLinkEntity dbLinkEntity, String table) throws Exception {
  309. NotTenantPluginHolder.setNotSwitchFlag();
  310. Integer total = JdbcUtil.queryOneInt(SqlComEnum.EXISTS_TABLE.getPrepSqlDto(dbLinkEntity, table), DbAliasEnum.TOTAL.getAlias());
  311. return total > 0;
  312. }
  313. public static List<DbTableFieldModel> getTableList(DbLinkEntity dbLinkEntity, String methodName) throws Exception {
  314. NotTenantPluginHolder.setNotSwitchFlag();
  315. List<DbTableFieldModel> list;
  316. if (StringUtil.isNotEmpty(methodName) && DbAliasEnum.TABLE_TYPE.getAlias().equals(methodName)) {
  317. list = JdbcUtil.queryCustomMods(SqlComEnum.TABLESANDVIEW.getPrepSqlDto(dbLinkEntity, ""), DbTableFieldModel.class);
  318. return list.stream().sorted(Comparator.comparing(DbTableFieldModel::getType).thenComparing(DbTableFieldModel::getTable)).collect(Collectors.toList());
  319. } else {
  320. list = JdbcUtil.queryCustomMods(SqlComEnum.TABLES.getPrepSqlDto(dbLinkEntity, ""), DbTableFieldModel.class);
  321. }
  322. // 排序
  323. return list.stream().sorted(Comparator.comparing(DbTableFieldModel::getTable)).collect(Collectors.toList());
  324. }
  325. public static List<DbTableFieldModel> getTableList(DbLinkEntity dbLinkEntity) throws Exception {
  326. return getTableList(dbLinkEntity, null);
  327. }
  328. public static DbTableFieldModel getTable(DbLinkEntity dbLinkEntity, String table) throws Exception {
  329. NotTenantPluginHolder.setNotSwitchFlag();
  330. List<DbTableFieldModel> dbTableFieldModelList =
  331. JdbcUtil.queryCustomMods(SqlComEnum.TABLE.getPrepSqlDto(dbLinkEntity, table), DbTableFieldModel.class);
  332. if(dbTableFieldModelList.size() < 1){
  333. throw new DataException(MsgCode.DB010.get(dbLinkEntity.getDbName(), table));
  334. }
  335. DbTableFieldModel dbTableFieldModel = dbTableFieldModelList.get(0);
  336. dbTableFieldModel.setDbEncode(dbLinkEntity.getDbType());
  337. return dbTableFieldModel;
  338. }
  339. }