HQL 转 SQL

应用场景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());
    }
相关文章
相关标签/搜索