應用場景java
在當前系統當中是分佈式微服務,A系統當中使用的是 Hibernate , 在B 系統當中使用是 Spring JDBCTemplate 衆所周知,這兩個數據持久框架使用的查詢語言徹底不同,雖然Hibernate 中的是可以使用 SQL直接查詢的 ,固然也有同窗會想到使用Hibernate 多庫解決,因爲實際生產當有不可描述的緣由不能這麼作,還會有同窗說使用Hibernate直接可轉換可是這種方式要求對象必須是在Hibernate中管理纔可實現轉換,本次任務當中是不存在Hibernate中管理ORM。sql
@Override public String doHqlToSql(String hqlQueryText) { QueryTranslatorFactory translatorFactory = new ASTQueryTranslatorFactory(); Session session = entityManager.unwrap(Session.class); SessionFactoryImplementor factory = (SessionFactoryImplementor) session.getSessionFactory(); QueryTranslator translator = translatorFactory.createQueryTranslator(hqlQueryText, hqlQueryText, Collections.EMPTY_MAP, factory,null); translator.compile(Collections.EMPTY_MAP, false); return translator.getSQLString(); }
在此場景中 A 系統調用 B 系統的查詢使用的是誇服務的Cloud 調用,傳輸過去的是HQL然而在B 系統當中須要進行一次HQL 轉 SQL才能執行,廢話也囉嗦了半天各位小夥伴是否已經忍耐好久啦 ! 哈哈哈看碼 ~!session
解決方法app
/** * HQL 轉 SQL * <per> * <br/> DEMO: "SELECT sui.id AS sui_id, sui.name AS sui_name, sui.userEmpNo AS sui_userEmpNo, sui.organizeCode AS sui_organizeCode, sui.departmentNameRdd AS sui_departmentNameRdd, su.userPhone AS su_userPhone FROM SysUserInfo AS sui left join SysUser AS su ON su.userInfoId = sui.id WHERE 1=1 AND sui.name LIKE :sui_name AND sui.userEmpNo LIKE :sui_userEmpNo" * <br/> 根據 DEMO HQL 的特色可分析得出 * <br/> 一、HQL是對象的方式進行查詢的,那麼Java 當中對象的方式必然都是以 . 的方式調用,因此屬性咱們能夠使用 . 關鍵字替換 * <br/> 二、對象必然都是在 FROM 值 WHERE 中間每一個對象都是有相應的別名的,因此根據AS 作文章進行截取轉換 * <br/> 實現邏輯: * <br/> 屬性改名: 根據 . 的位置找出須要替換的屬性 而後轉換 加入到行的 String當中 * <br/> 對象改名: * <br/> 因爲 AS 是在對象後面的那麼咱們須要對String 進行反向截取,一樣須要先找出 AS 位置而後進行對象改名操做 * <br/> 最終在處理完成後須要String 順序反轉一次 * <br/> 注意事項: * <br/> 未作處理HQL * <br/> SELECT FROM SysUser * <br/> FROM SysUser * <br/> HQL 必要條件 * <br/> 對象必需要有 AS * </per> * @param hql * @return sql */ public static String getHqlToSQL(String hql){ StringBuffer sql = new StringBuffer(); if (StringUtils.isNotBlank(hql)) { char[] hqlCharArr = hql.toCharArray(); int indexStart = -1; int indexEnd = -1; /** * 更改字段名稱(實現原理) * 一、根據HQL 的特色 . 找出屬性開始位置 * 二、找出屬性結束位置 ' ' * 三、替換 屬性名稱 */ for (int i = 0; i < hqlCharArr.length; i++) { char letter = hqlCharArr[i]; if (letter == '.') { // 找出開始位置 indexStart = i; } if (indexStart != -1 && letter == ' ') { // 找出結束位置 indexEnd = i; } if (indexStart != -1 && indexEnd != -1) { // 字符串替換 char[] replace = Arrays.copyOfRange(hqlCharArr, indexStart, indexEnd); sql.append(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, new String(replace))); indexStart = -1; indexEnd = -1; } if (indexStart == -1) { sql.append(letter); } } hqlCharArr = sql.toString().toCharArray(); int fromIndex = sql.indexOf("FROM") + 4; int whereIndex = sql.indexOf("WHERE"); int fromObjectEnd = -1; int fromObjectStart = -1; sql = new StringBuffer(); /** * 更新對象名稱(實現原理) * 一、HQL 的對象是在 FROM 至 WHERE 中間 * 二、根據 AS 的位置找出 須要截取的 截止位置 * 三、根據 ' ' 找出須要替換的開始位置 * 四、替換 對象名稱 */ for (int i = hqlCharArr.length - 1 ; i >= 0; i--) { char letter = hqlCharArr[i]; if(i < whereIndex && i > fromIndex){ if(letter == 'S' && hqlCharArr[i - 1] == 'A'){ fromObjectEnd = i - 2; } if(fromObjectEnd != -1 && fromObjectEnd != i && letter == ' '){ fromObjectStart = i + 1; } } if (fromObjectStart != -1 && fromObjectEnd != -1) { char[] replace = Arrays.copyOfRange(hqlCharArr, fromObjectStart, fromObjectEnd); sql.append(StringUtils.reverse(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE,new String(replace)))); fromObjectStart = -1; fromObjectEnd = -1; } if(fromObjectEnd == -1){ sql.append(letter); } } } return StringUtils.reverse(sql.toString()); }