16
votes

I am executing the following HQL and it is executing properly

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

Now, I also want to log the sql generated at the backend in logs for support users.

I want to make use of QueryTranslator please advise how can I generate the sql for the corresponding HQL please advise how to achieve this.

7

7 Answers

7
votes

You can use 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();
5
votes

I believe you want a combination of the top 2 answers

  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();
3
votes

This is also possible with TypedQuery in later versions of Hibernate using the following code

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();
2
votes

I found next solution on the web:

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(); 

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

1
votes

This works, other answers have a problem for modern versions of hibernate:

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();
1
votes

Hibernate Types

Starting with the 2.9.11 version, the Hibernate Types open-source project offers the SQLExtractor utility that allows you to get the SQL query from any JPQL or Criteria API query, no matter you are using Hibernate 5.4, 5.3, 5.2, 5.1, 5.0, 4.3, 4.2, or 4.1.

Get the SQL statement from a JPQL (HQL) Query

Let's assume we have the following JPQL (HQL) query:

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

With Hibernate Types, extracting the Hibernate-generated SQL query is as simple as that:

String sql = SQLExtractor.from(jpql);

And, if we log the extracted SQL query:

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

We get the following output:

- 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)
]

Notice that we unwrapped the JPQL (HQL) Query to the Hibernate org.hibernate.query.Query interface which provided the getQueryString method we can use to log the associated JPQL query string.

-2
votes

you can get the Query out by using the unwrap method.

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