SqlUtils.java 21 KB

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