SQLCreatorFactory.java 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. package com.primeton.dsp.datarelease.api.sql;
  2. import com.google.common.collect.Sets;
  3. import com.primeton.dsp.datarelease.api.model.JoinPair;
  4. import com.primeton.dsp.datarelease.api.model.Table;
  5. import com.primeton.dsp.datarelease.api.model.WhereCause;
  6. import lombok.extern.slf4j.Slf4j;
  7. import org.apache.commons.lang.StringUtils;
  8. import java.util.ArrayList;
  9. import java.util.HashMap;
  10. import java.util.List;
  11. import java.util.Map;
  12. import java.util.Set;
  13. /**
  14. *
  15. * 服务发布多表关联,和单表 服务发布时生成预览SQL。
  16. *
  17. * <pre>
  18. *
  19. * Created by zhaopx.
  20. * User: zhaopx
  21. * Date: 2020/3/27
  22. * Time: 17:15
  23. *
  24. * </pre>
  25. *
  26. * @author zhaopx
  27. */
  28. @Slf4j
  29. public abstract class SQLCreatorFactory {
  30. /**
  31. * 单表生成 SQL
  32. * @return
  33. */
  34. public abstract String singleTable(Table table, WhereCause[] conds);
  35. /**
  36. * 多表生成 SQL
  37. *
  38. * @param tables
  39. * @param joins
  40. * @param conds
  41. * @return
  42. */
  43. public abstract String mutilTable(Table[] tables, JoinPair[] joins, WhereCause[] conds);
  44. /**
  45. * 生成一个实例
  46. * @return
  47. */
  48. public static SQLCreatorFactory newInstance() {
  49. return new SQLCreatorFactory() {
  50. @Override
  51. public String singleTable(Table table, WhereCause[] conds) {
  52. //单表生成SQL预览
  53. SQLQuery sqlQuery = new SQLQuery.Builder(table)
  54. .where(conds)
  55. .build();
  56. //生成的SQL要预览,这里美化一下
  57. String showSQL = sqlQuery.show(true);
  58. log.info("c sql {}", showSQL);
  59. return showSQL;
  60. }
  61. @Override
  62. public String mutilTable(Table[] tables, JoinPair[] joins, WhereCause[] conds) {
  63. Map<String, SQLJoin.JoinTable> tableMapping = new HashMap<>();
  64. for(Table table : tables) {
  65. tableMapping.put(table.getTableName(), new SQLJoin.JoinTable(table));
  66. }
  67. // join 条件,如果量表 join 多次也当做 where
  68. List<JoinPair> joinList = new ArrayList<>();
  69. // where 条件,把多余的 join 条件放到 where 条件中
  70. Set<WhereCause> condSet = Sets.newHashSet(conds);
  71. // 相同的两个表,join 多次的情况,取第一个作为 join,后面的作为 where 条件
  72. Map<String, JoinPair> joinPairCache = new HashMap<>();
  73. for(JoinPair jp : joins) {
  74. //左表加右表
  75. String cacheKey = StringUtils.upperCase(jp.getLeft() + jp.getRight());
  76. if(joinPairCache.get(cacheKey) == null) {
  77. joinPairCache.put(cacheKey, jp);
  78. joinList.add(jp);
  79. } else {
  80. // 已经存在关联的 join 转为 where 后的条件
  81. WhereCause cause = new WhereCause();
  82. cause.setTableName(jp.getLeft());
  83. cause.setFieldName(jp.getLeftField());
  84. cause.setToTableName(jp.getRight());
  85. cause.setToFieldName(jp.getRightField());
  86. cause.setOpera("=");
  87. condSet.add(cause);
  88. }
  89. }
  90. SQLJoin.Builder builder = null;
  91. if(joinList.size() == 1) {
  92. // 2 个表的关联
  93. SQLJoin.JoinTable left = tableMapping.get(joinList.get(0).getLeft());
  94. SQLJoin.JoinTable right = tableMapping.get(joinList.get(0).getRight());
  95. builder = new SQLJoin.Builder(left, joinList.get(0).getLeftField(),
  96. right, joinList.get(0).getRightField(),
  97. SQLJoin.JoinType.joinType(joinList.get(0).getJoinType()));
  98. } else {
  99. // 3 个或者3 个以上的表关联
  100. SQLJoin.JoinTable left = tableMapping.get(joinList.get(0).getLeft());
  101. SQLJoin.JoinTable right = tableMapping.get(joinList.get(0).getRight());
  102. builder = new SQLJoin.Builder(left, joinList.get(0).getLeftField(),
  103. right, joinList.get(0).getRightField(),
  104. SQLJoin.JoinType.joinType(joinList.get(0).getJoinType()));
  105. for(int i = 1; i < joinList.size(); i++) {
  106. JoinPair joinPair = joinList.get(i);
  107. SQLJoin.JoinTable leftTable = tableMapping.get(joinPair.getLeft());
  108. SQLJoin.JoinTable rightTable = tableMapping.get(joinPair.getRight());
  109. // 下面使用要重新 new 一个,防止重新设置别名是影响原来的别名
  110. if(builder.isCachedTable(leftTable.getTableName())) {
  111. //A JOIN B JOIN C, 正好是符合的
  112. builder.join(leftTable,
  113. joinPair.getLeftField(),
  114. rightTable,
  115. joinPair.getRightField(),
  116. SQLJoin.JoinType.joinType(joinPair.getJoinType()));
  117. } else {
  118. // A JOIN C
  119. // B JOIN C 模式,生成 JOIN 应该是 A JOIN C JOIN B 的方式
  120. SQLJoin.JoinType joinType = SQLJoin.JoinType.joinType(joinPair.getJoinType());
  121. SQLJoin.JoinType realJoinType = joinType;
  122. switch (joinType) {
  123. case LEFT_JOIN:
  124. realJoinType = SQLJoin.JoinType.RIGHT_JOIN;
  125. break;
  126. case RIGHT_JOIN:
  127. realJoinType = SQLJoin.JoinType.LEFT_JOIN;
  128. break;
  129. default:
  130. }
  131. // 调换一下顺序
  132. builder.join(
  133. rightTable,
  134. joinPair.getRightField(),
  135. leftTable,
  136. joinPair.getLeftField(),
  137. realJoinType);
  138. }
  139. }
  140. }
  141. // 把where 条件加入进来
  142. builder.where(condSet);
  143. SQLJoin sql = builder.build();
  144. // 前端不显示 SQL,如果加了回车在执行时会乱码报错。因此这里不能加回车进行格式化
  145. String resultSql = sql.show(true);
  146. log.info(resultSql);
  147. return resultSql;
  148. }
  149. };
  150. }
  151. }