SqlUtils.java 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. package com.kingdee.eas.custom.dataconfig.utils;
  2. import com.alibaba.fastjson.JSONArray;
  3. import com.alibaba.fastjson.JSONObject;
  4. import com.kingdee.bos.Context;
  5. import com.kingdee.bos.metadata.data.ColumnInfo;
  6. import com.kingdee.bos.metadata.entity.*;
  7. import com.kingdee.eas.custom.entryconfig.DataConfigSelectFieldEntryCollection;
  8. import com.kingdee.eas.custom.entryconfig.DataConfigSelectFieldEntryInfo;
  9. import com.kingdee.shr.base.syssetting.util.MetaDataUtil;
  10. /**
  11. * SQL工具类,提供实体信息获取、SQL语句构建(关联表JOIN)以及查询字段信息JSON生成等功能
  12. */
  13. public class SqlUtils {
  14. /**
  15. * 根据实体名称获取实体对象信息
  16. * @param name 实体名称
  17. * @param context 上下文对象(此处未实际使用,保留参数可能为扩展用)
  18. * @return 实体对象信息EntityObjectInfo
  19. */
  20. public EntityObjectInfo getEntryInfo(String name, Context context) {
  21. // 调用MetaDataUtil工具类根据实体名称获取实体对象信息
  22. return MetaDataUtil.getEntityObjectByEntityName(name);
  23. }
  24. /**
  25. * 构建SQL语句中的表连接部分(包括主表和关联表的LEFT JOIN)
  26. * @param sql 用于拼接SQL的StringBuilder对象
  27. * @param entityObjectInfo 实体对象信息,用于获取表名和属性信息
  28. * @param alias 表的别名,如果为null或空则使用实体真实名称作为别名
  29. * @param context 上下文对象(此处未实际使用,保留参数可能为扩展用)
  30. * @param isHead 是否为主表(头部表),主表不需要ON条件
  31. * @param on 连接条件,当isHead为false时使用
  32. */
  33. public void getSql(StringBuilder sql, EntityObjectInfo entityObjectInfo, String alias
  34. , Context context, Boolean isHead, String on) {
  35. // 如果别名为空或空字符串,则使用实体的真实名称作为别名
  36. if (alias == null || alias.equals("")) {
  37. String realName = entityObjectInfo.getRealName();
  38. alias = realName;
  39. }
  40. // 获取实体对应的数据库表名
  41. String name = entityObjectInfo.getTable().getName();
  42. // 拼接表名和别名到SQL中(如:table_name as "alias")
  43. sql.append(name + " as ").append("\"" + alias + "\"").append("\n");
  44. // 如果不是主表,则拼接ON条件
  45. if (!isHead) {
  46. sql.append("on " + on).append("\n");
  47. }
  48. // 获取实体所有非重复的继承属性集合
  49. PropertyCollection properties = entityObjectInfo.getInheritedNoDuplicatedProperties();
  50. // 遍历属性集合
  51. for (int i = 0; i < properties.size(); i++) {
  52. PropertyInfo propertyInfo = properties.get(i);
  53. // 判断当前属性是否为关联属性(LinkPropertyInfo)
  54. if (propertyInfo instanceof LinkPropertyInfo) {
  55. // 生成关联表的别名(当前属性名 + 主表别名)
  56. String name1 = propertyInfo.getName() + alias;
  57. // 获取关联属性对应的映射字段(数据库列)
  58. ColumnInfo mappingField = propertyInfo.getMappingField();
  59. // 如果映射字段为空,则跳过当前属性
  60. if (mappingField == null) {
  61. continue;
  62. }
  63. // 获取映射字段的名称(数据库列名)
  64. String mappingFieldName = mappingField.getName();
  65. // 获取关联属性指向的目标实体对应的表名
  66. String tableName = ((LinkPropertyInfo) propertyInfo).getRelationship().getSupplierObject().getTable().getName();
  67. // 强制转换为LinkPropertyInfo以便获取关联关系
  68. LinkPropertyInfo linkPropertyInfo = ((LinkPropertyInfo) propertyInfo);
  69. RelationshipInfo r = linkPropertyInfo.getRelationship();
  70. // 获取目标实体的全限定名
  71. String fullName = r.getSupplierObject().getFullName();
  72. // 拼接LEFT JOIN语句,关联目标表(如:left join target_table as "name1")
  73. sql.append("left join ").append(tableName).append(" as ").append("\"" + name1 + "\"").append("\n");
  74. // 拼接关联条件(主表别名.映射列名 = 关联表别名.FID)
  75. sql.append("on \"" + alias + "\".\"" + mappingFieldName + "\" = " + " \"" + name1 + "\".\"FID" + "\" ").append("\n");
  76. // 根据目标实体全限定名获取其实体对象信息
  77. EntityObjectInfo entryInfo = this.getEntryInfo(fullName, context);
  78. // 获取目标实体的所有非重复继承属性集合
  79. PropertyCollection propertiesChildren = entryInfo.getInheritedNoDuplicatedProperties();
  80. // 遍历目标实体的属性集合(处理二级关联)
  81. for (int j = 0; j < propertiesChildren.size(); j++) {
  82. PropertyInfo propertyChildren = propertiesChildren.get(j);
  83. // 判断二级属性是否为关联属性
  84. if (propertyChildren instanceof LinkPropertyInfo) {
  85. // 生成二级关联表的别名(一级关联表别名.二级属性名)
  86. String asTableChildren = name1 + "." + propertyChildren.getName();
  87. // 获取二级关联属性的映射字段
  88. ColumnInfo mappingFieldChildren = propertyChildren.getMappingField();
  89. // 如果映射字段为空,则跳过当前二级属性
  90. if (mappingFieldChildren == null) {
  91. continue;
  92. }
  93. // 获取二级关联属性指向的目标表名
  94. String tableChildren = ((LinkPropertyInfo) propertyChildren).getRelationship().getSupplierObject().getTable().getName();
  95. // 获取二级映射字段的名称(数据库列名)
  96. String mappingFieldNameChildren = mappingFieldChildren.getName();
  97. // 拼接二级LEFT JOIN语句(如:left join child_table as "asTableChildren")
  98. sql.append("left join ").append(tableChildren).append(" as ").append("\"" + asTableChildren + "\"").append("\n");
  99. // 拼接二级关联条件(一级关联表别名.二级映射列名 = 二级关联表别名.FID)
  100. sql.append("on \"" + name1 + "\".\"" + mappingFieldNameChildren + "\" = " + " \"" + asTableChildren + "\".\"FID" + "\" ").append("\n");
  101. }
  102. }
  103. }
  104. }
  105. }
  106. /**
  107. * 生成查询字段的信息JSON数组,包含字段名、别名、数据类型、映射关系等
  108. * @param entityObjectInfo 实体对象信息,用于获取属性信息
  109. * @param alias 表别名,用于构建字段映射路径
  110. * @param context 上下文对象(用于获取关联实体信息)
  111. * @return 包含字段信息的JSONArray
  112. */
  113. public JSONArray getSelectField(EntityObjectInfo entityObjectInfo, String alias, Context context) {
  114. // 如果别名为空或空白,则默认使用实体的真实名称作为别名
  115. if (alias == null || alias.trim().isEmpty()) {
  116. alias = entityObjectInfo.getRealName();
  117. }
  118. // 获取实体所有非重复的继承属性集合
  119. PropertyCollection properties = entityObjectInfo.getInheritedNoDuplicatedProperties();
  120. JSONArray resultArray = new JSONArray(); // 用于存储返回的字段信息JSON数组
  121. // 遍历实体属性集合
  122. for (int i = 0; i < properties.size(); i++) {
  123. PropertyInfo propertyInfo = properties.get(i);
  124. JSONObject currentJson = new JSONObject(); // 存储当前属性的信息JSON对象
  125. // 判断当前属性是否为关联属性(LinkPropertyInfo)
  126. if (propertyInfo instanceof LinkPropertyInfo) {
  127. // 强制转换为LinkPropertyInfo
  128. LinkPropertyInfo linkProperty = (LinkPropertyInfo) propertyInfo;
  129. String fieldName = linkProperty.getName(); // 属性名称
  130. String fieldAlias = linkProperty.getAlias(); // 属性别名
  131. // 设置当前关联属性的基础信息
  132. currentJson.put("field", alias+"."+fieldName);
  133. currentJson.put("name", fieldAlias);
  134. currentJson.put("dataType", DataType.OBJECTVALUE.getName());
  135. // 获取关联属性的映射字段(数据库列)
  136. ColumnInfo mappingField = linkProperty.getMappingField();
  137. if (mappingField == null) {
  138. continue; // 若映射字段为空,则跳过当前属性
  139. }
  140. // 获取关联关系信息
  141. RelationshipInfo relationship = linkProperty.getRelationship();
  142. // 获取关联目标实体的全限定名(作为枚举来源)
  143. String enumSource = relationship.getSupplierObject().getFullName();
  144. currentJson.put("enumSource", enumSource);
  145. // 根据目标实体全限定名获取其实体对象信息
  146. EntityObjectInfo relatedEntity = this.getEntryInfo(enumSource, context);
  147. // 获取目标实体的所有非重复继承属性集合(子属性)
  148. PropertyCollection childProperties = relatedEntity.getInheritedNoDuplicatedProperties();
  149. JSONArray childrenArray = new JSONArray(); // 存储子属性信息的JSON数组
  150. String realName = relatedEntity.getRealName();
  151. // 遍历目标实体的子属性
  152. for (int j = 0; j < childProperties.size(); j++) {
  153. PropertyInfo childProperty = childProperties.get(j);
  154. JSONObject childJson = new JSONObject(); // 存储当前子属性的信息JSON对象
  155. // 设置子属性的基础信息
  156. childJson.put("field", alias+"."+realName+"."+childProperty.getName());
  157. childJson.put("name", childProperty.getAlias());
  158. childJson.put("dataType", DataType.OBJECTVALUE.getName());
  159. // 判断子属性是否为关联属性(二级关联)
  160. if (childProperty instanceof LinkPropertyInfo) {
  161. // 强制转换为LinkPropertyInfo
  162. LinkPropertyInfo childLink = (LinkPropertyInfo) childProperty;
  163. // 获取二级关联属性的映射字段
  164. ColumnInfo childMappingField = childLink.getMappingField();
  165. if (childMappingField == null) {
  166. continue; // 若映射字段为空,则跳过当前子属性
  167. }
  168. // 获取二级关联关系信息
  169. RelationshipInfo childRelationship = childLink.getRelationship();
  170. // 获取二级关联目标实体的全限定名
  171. String childEnumSource = childRelationship.getSupplierObject().getFullName();
  172. // 避免循环关联(若二级关联目标与一级关联目标相同,则跳过)
  173. if (childEnumSource.equals(enumSource)) {
  174. continue;
  175. }
  176. childJson.put("enumSource", childEnumSource);
  177. // 根据二级关联目标实体全限定名获取其实体对象信息
  178. EntityObjectInfo grandChildEntity = this.getEntryInfo(childEnumSource, context);
  179. // 获取二级目标实体的所有非重复继承属性集合(孙属性)
  180. PropertyCollection grandChildProperties = grandChildEntity.getInheritedNoDuplicatedProperties();
  181. JSONArray grandChildArray = new JSONArray(); // 存储孙属性信息的JSON数组
  182. // 遍历孙属性
  183. for (int k = 0; k < grandChildProperties.size(); k++) {
  184. PropertyInfo grandChildProperty = grandChildProperties.get(k);
  185. // 只处理自有属性(OwnPropertyInfo),跳过关联属性
  186. if (!(grandChildProperty instanceof OwnPropertyInfo)) {
  187. continue;
  188. }
  189. // 强制转换为OwnPropertyInfo
  190. OwnPropertyInfo ownGrandChild = (OwnPropertyInfo) grandChildProperty;
  191. JSONObject grandChildJson = new JSONObject();
  192. // 设置孙属性的基础信息
  193. grandChildJson.put("field", alias+"."+realName+"."+childProperty.getName()+"."+ownGrandChild.getName());
  194. grandChildJson.put("name", ownGrandChild.getAlias());
  195. grandChildJson.put("dataType", ownGrandChild.getDataType().getName());
  196. // 若孙属性为枚举类型,设置枚举来源
  197. if (ownGrandChild.getDataType().getName().equals("Enum")) {
  198. grandChildJson.put("enumSource", ownGrandChild.getEnumType().getFullName());
  199. grandChildJson.put("enumData", ownGrandChild.getEnumType().getEnumValue());
  200. }
  201. // 处理孙属性的数据库字段映射(考虑多语言)
  202. boolean isMultilingual = ownGrandChild.getMappingField().isMultilingual();
  203. // 构建父字段路径(一级关联别名.二级属性名)
  204. String parentFieldPath = fieldName + alias + "." + childProperty.getName();
  205. // 获取孙属性对应的数据库列名
  206. String dbFieldName = ownGrandChild.getMappingField().getName();
  207. String mappingFieldVal; // 数据库字段引用(如:"alias.field"."dbColumn")
  208. String asMappingFieldVal; // 字段别名(如:"alias.field.dbColumn")
  209. // 多语言字段拼接_l2后缀(可能为特定语言标识)
  210. if (isMultilingual) {
  211. mappingFieldVal = "\"" + parentFieldPath + "\"." + dbFieldName + "_l2";
  212. asMappingFieldVal = "\"" + parentFieldPath + "." + dbFieldName + "_l2\"";
  213. } else {
  214. mappingFieldVal = "\"" + parentFieldPath + "\"." + dbFieldName;
  215. asMappingFieldVal = "\"" + parentFieldPath + "." + dbFieldName + "\"";
  216. }
  217. grandChildJson.put("mappingField", mappingFieldVal);
  218. grandChildJson.put("asMappingField", asMappingFieldVal);
  219. // 将孙属性信息添加到孙属性数组
  220. grandChildArray.add(grandChildJson);
  221. }
  222. // 将孙属性数组添加到当前子属性的JSON中
  223. childJson.put("children", grandChildArray);
  224. } else if (childProperty instanceof OwnPropertyInfo) {
  225. // 子属性为自有属性(OwnPropertyInfo)
  226. OwnPropertyInfo ownChild = (OwnPropertyInfo) childProperty;
  227. // 设置子属性的数据类型
  228. childJson.put("dataType", ownChild.getDataType().getName());
  229. // 若子属性为枚举类型,设置枚举来源
  230. if (ownChild.getDataType().getName().equals("Enum")) {
  231. childJson.put("enumSource", ownChild.getEnumType().getFullName());
  232. childJson.put("enumData", ownChild.getEnumType().getEnumValue());
  233. }
  234. // 处理子属性的数据库字段映射(考虑多语言)
  235. boolean isMultilingual = ownChild.getMappingField().isMultilingual();
  236. // 获取子属性对应的数据库列名
  237. String dbFieldName = ownChild.getMappingField().getName();
  238. String mappingFieldVal; // 数据库字段引用
  239. String asMappingFieldVal; // 字段别名
  240. // 多语言字段拼接_l2后缀
  241. if (isMultilingual) {
  242. mappingFieldVal = "\"" + fieldName + alias + "\"." + dbFieldName + "_l2";
  243. asMappingFieldVal = "\"" + fieldName + alias + "." + dbFieldName + "_l2\"";
  244. } else {
  245. mappingFieldVal = "\"" + fieldName + alias + "\"." + dbFieldName;
  246. asMappingFieldVal = "\"" + fieldName + alias + "." + dbFieldName + "\"";
  247. }
  248. childJson.put("mappingField", mappingFieldVal);
  249. childJson.put("asMappingField", asMappingFieldVal);
  250. }
  251. // 将子属性信息添加到子属性数组
  252. childrenArray.add(childJson);
  253. }
  254. // 将子属性数组添加到当前关联属性的JSON中
  255. currentJson.put("children", childrenArray);
  256. // 将当前关联属性信息添加到结果数组
  257. resultArray.add(currentJson);
  258. } else if (propertyInfo instanceof OwnPropertyInfo) {
  259. // 当前属性为自有属性(OwnPropertyInfo)
  260. OwnPropertyInfo ownProperty = (OwnPropertyInfo) propertyInfo;
  261. String fieldName = ownProperty.getName(); // 属性名称
  262. String dbFieldName = ownProperty.getMappingField().getName(); // 对应的数据库列名
  263. // 设置自有属性的基础信息
  264. currentJson.put("field", alias+"."+fieldName);
  265. currentJson.put("name", ownProperty.getAlias());
  266. currentJson.put("dataType", ownProperty.getDataType().getName());
  267. // 若自有属性为枚举类型,设置枚举来源
  268. if (ownProperty.getDataType().getName().equals("Enum")) {
  269. currentJson.put("enumSource", ownProperty.getEnumType().getFullName());
  270. currentJson.put("enumData", ownProperty.getEnumType().getEnumValue());
  271. }
  272. // 处理自有属性的数据库字段映射(考虑多语言)
  273. boolean isMultilingual = ownProperty.getMappingField().isMultilingual();
  274. String mappingFieldVal; // 数据库字段引用
  275. String asMappingFieldVal; // 字段别名
  276. // 多语言字段拼接_l2后缀
  277. if (isMultilingual) {
  278. mappingFieldVal = "\"" + alias + "\"." + dbFieldName + "_l2";
  279. asMappingFieldVal = "\"" + alias + "." + dbFieldName + "_l2\"";
  280. } else {
  281. mappingFieldVal = "\"" + alias + "\"." + dbFieldName;
  282. asMappingFieldVal = "\"" + alias + "." + dbFieldName + "\"";
  283. }
  284. currentJson.put("mappingField", mappingFieldVal);
  285. currentJson.put("asMappingField", asMappingFieldVal);
  286. // 将当前自有属性信息添加到结果数组
  287. resultArray.add(currentJson);
  288. }
  289. }
  290. // 返回包含所有字段信息的JSON数组
  291. return resultArray;
  292. }
  293. public StringBuilder getSelectField(DataConfigSelectFieldEntryCollection fieldEntry,StringBuilder sql){
  294. for (int i = 0; i < fieldEntry.size(); i++) {
  295. DataConfigSelectFieldEntryInfo entryInfo = fieldEntry.get(i);
  296. String databaseName = entryInfo.getDatabaseName();
  297. String mappingKey = entryInfo.getMappingKey();
  298. sql.append(databaseName).append(" as ").append(mappingKey);
  299. if (i==fieldEntry.size()-1){
  300. sql.append("\n");
  301. }else {
  302. sql.append(" , ").append("\n");
  303. }
  304. }
  305. return sql;
  306. }
  307. }