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());
    }
相關文章
相關標籤/搜索