【问题标题】:How to convert HQL to SQL Query programmatically (without logging)如何以编程方式将 HQL 转换为 SQL 查询(不记录)
【发布时间】:2013-08-25 09:22:12
【问题描述】:

我正在执行以下 HQL,它正在正确执行

String hql = "FROM Employee";
Query query = session.createQuery(hql);
List results = query.list();

现在,我还想将后端生成的 sql 记录在日志中以供支持用户使用。

我想使用QueryTranslator,请指教如何为相应的HQL生成sql,请指教如何实现。

【问题讨论】:

    标签: java sql hibernate hql jpql


    【解决方案1】:

    你可以使用hibernate QueryTranslator:

    String hqlQueryString = hqlQuery.getQueryString();
    ASTQueryTranslatorFactory queryTranslatorFactory = new ASTQueryTranslatorFactory();
    SessionImplementor hibernateSession = entityManager.unwrap(SessionImplementor.class);
    QueryTranslator queryTranslator = queryTranslatorFactory.createQueryTranslator("", hqlQueryString, java.util.Collections.EMPTY_MAP, hibernateSession.getFactory());
    queryTranslator.compile(java.util.Collections.EMPTY_MAP, false);
    String sqlQueryString = queryTranslator.getSQLString();
    

    【讨论】:

    • 不幸的是,这不适用于 Hibernate 5 :( 有新的第 5 个参数 EntityGraphQueryHint
    • 您可以将 null 作为第 5 个参数传递。它应该可以工作。
    • 这只会返回 hql 而不是 sql;问题是:“现在我还想将后端生成的 sql 记录在支持用户的日志中”
    • 代码最终返回“sqlQueryString”变量中hqlQuery的SQL等价。
    • 很遗憾没有使用列的别名。
    【解决方案2】:

    我相信您想要前 2 个答案的组合

      String hqlQueryString = query.unwrap(org.hibernate.Query.class).getQueryString();
      ASTQueryTranslatorFactory queryTranslatorFactory = new ASTQueryTranslatorFactory();
      SessionImplementor hibernateSession = em.unwrap(SessionImplementor.class);
      QueryTranslator queryTranslator = queryTranslatorFactory.createQueryTranslator("", hqlQueryString, java.util.Collections.EMPTY_MAP, hibernateSession.getFactory());
      queryTranslator.compile(java.util.Collections.EMPTY_MAP, false);
      String sqlQueryString = queryTranslator.getSQLString();
    

    【讨论】:

    • createQueryTranslator 还需要一个参数:EntityGraphQueryHint
    • 翻译后,“:variable”等参数全部被“?”替换,无法设置参数值。我也尝试设置参数,然后将其转换为 SQL,但效果不佳。注意:我这样做是为了将其附加为计数的子查询,因为 group by 内有许多参数,而 HQL 不支持这个
    【解决方案3】:

    在 Hibernate 的更高版本中使用 TypedQuery 也可以使用以下代码

    String hqlQueryString=typedQuery.unwrap(org.hibernate.query.Query.class).getQueryString();
            ASTQueryTranslatorFactory queryTranslatorFactory = new ASTQueryTranslatorFactory();
            SessionImplementor hibernateSession = entityManager.unwrap(SessionImplementor.class);
            QueryTranslator queryTranslator = queryTranslatorFactory.createQueryTranslator("", hqlQueryString, java.util.Collections.EMPTY_MAP, hibernateSession.getFactory(), null);
            queryTranslator.compile(java.util.Collections.EMPTY_MAP, false);
            String sqlQueryString = queryTranslator.getSQLString();
    

    【讨论】:

      【解决方案4】:

      我在网上找到了下一个解决方案:

      QueryTranslatorFactory translatorFactory = new ASTQueryTranslatorFactory();
      SessionFactoryImplementor factory = (SessionFactoryImplementor) getSessionFactory();
      QueryTranslator translator = translatorFactory.
              createQueryTranslator(hqlQueryText, hqlQueryText, Collections.EMPTY_MAP, factory);
      translator.compile(Collections.EMPTY_MAP, false);
      translator.getSQLString(); 
      

      来源:http://narcanti.keyboardsamurais.de/hibernate-hql-to-sql-translation.html

      【讨论】:

        【解决方案5】:

        这行得通,其他答案对于现代版本的休眠有问题:

        String hqlQueryString = query.unwrap(org.hibernate.Query.class).getQueryString();
        ASTQueryTranslatorFactory queryTranslatorFactory = new ASTQueryTranslatorFactory();
        SessionImplementor hibernateSession = entityManager.unwrap(SessionImplementor.class);
        QueryTranslator queryTranslator = queryTranslatorFactory.createQueryTranslator("", hqlQueryString, java.util.Collections.EMPTY_MAP, hibernateSession.getFactory(), null);
        queryTranslator.compile(java.util.Collections.EMPTY_MAP, false);
        String sqlQueryString = queryTranslator.getSQLString();
        

        【讨论】:

        • 今天这对我有用...似乎有这个问题的几个版本飞来飞去...
        【解决方案6】:

        休眠类型

        从 2.9.11 版本开始,Hibernate Types 开源项目提供了SQLExtractor 实用程序,允许您从任何 JPQL 或 Criteria API 查询中获取 SQL 查询,无论您使用的是 Hibernate 5.4、5.3 、5.2、5.1、5.0、4.3、4.2 或 4.1。

        从 JPQL (HQL) 查询中获取 SQL 语句

        假设我们有以下 JPQL (HQL) 查询:

        Query jpql = entityManager.createQuery("""
            select 
               YEAR(p.createdOn) as year, 
               count(p) as postCount 
            from 
               Post p 
            group by 
               YEAR(p.createdOn)
            """, Tuple.class
        );
        

        使用 Hibernate 类型,提取 Hibernate 生成的 SQL 查询就这么简单:

        String sql = SQLExtractor.from(jpql);
        

        而且,如果我们记录提取的 SQL 查询:

        LOGGER.info("""
            The JPQL query: [
                {}
            ]
            generates the following SQL query: [ 
                {}
            ]
            """,
            jpql.unwrap(org.hibernate.query.Query.class).getQueryString(),
            sql
        );
        

        我们得到以下输出:

        - The JPQL query: [
            select    
                YEAR(p.createdOn) as year,    
                count(p) as postCount 
            from    
                Post p 
            group by    
                YEAR(p.createdOn)
        ]
        generates the following SQL query: [
            SELECT 
                extract(YEAR FROM sqlextract0_.created_on) AS col_0_0_,
                count(sqlextract0_.id) AS col_1_0_
            FROM 
                post p
            GROUP BY 
                extract(YEAR FROM p.created_on)
        ]
        

        请注意,我们将 JPQL (HQL) Query 解包到 Hibernate org.hibernate.query.Query 接口,该接口提供了 getQueryString 方法,我们可以使用该方法记录关联的 JPQL 查询字符串。

        【讨论】:

          【解决方案7】:

          您可以使用 unwrap 方法获取查询。

          String queryString = query.unwrap(org.hibernate.Query.class).getQueryString();
          

          【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-06-20
          • 2013-07-02
          • 2014-06-26
          • 1970-01-01
          • 2020-03-28
          • 1970-01-01
          • 2016-01-27
          • 2021-11-02
          相关资源
          最近更新 更多