应用场景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()); }