Imagine having a tool that can automatically detect JPA and Hibernate performance issues.
Hypersistence Optimizer is that tool!
Introduction
In this article, we are going to see what JPA query hints are, and get to know all the query hints supported by Hibernate.
Understanding the Hibernate query hints is very important when developing a non-trivial enterprise application since they allow you to customize the way queries are executed by Hibernate.
The Java Persistence API defines the notion of query hint, which unlike what its name might suggest, it has nothing to do with database query hints. The JPA query hint is a Java Persistence provider customization option.
To pass a query hint, the JPA specification defines the setHint method of the javax.persistence.Query interface.
javax.persistence.query.timeout
The very first query hint supported by the JPA standard was the javax.persistence.query.timeout one which defined the number of milliseconds a given JPA query is allowed to run for. Behind the scenes, this hint will instruct Hibernate to call the PreparedStatement.setQueryTimeout method for the associated SQL query that gets executed.
The following example shows you how to set up the javax.persistence.query.timeout JPA query hint.
List<Post> posts = entityManager
.createQuery(
"select p " +
"from Post p " +
"where lower(p.title) like lower(:titlePattern)", Post.class)
.setParameter("titlePattern", "%Hibernate%")
.setHint("javax.persistence.query.timeout", 50)
.getResultList();
javax.persistence.fetchgraph
JPA 2.1 introduced the javax.persistence.fetchgraph query hint as well to provide a query-specific fetch graph that overrides the default fetch plan defined by the entity mapping.
According to the JPA specification, the javax.persistence.fetchgraph query hint should fetch eagerly only the associations that are explicitly specified by the currently provided fetch graph while the remaining association should be fetched lazily.
However, because lazy fetching is a non-mandatory requirement, the Hibernate behavior for the javax.persistence.fetchgraph query hint is different as the associations not specified by the provided fetch graph are fetched according to their entity mapping fetching strategy.
The javax.persistence.fetchgraph query hint can be specified as follows:
JPA 2.1 introduced the javax.persistence.loadgraph query hint as well to provide a query-specific fetch graph that overrides the default fetch plan defined by the entity mapping.
According to the JPA specification, the javax.persistence.loadgraph query hint should fetch eagerly only the associations that are explicitly specified by the currently provided fetch graph while the remaining association should be fetched according to their mapping fetching strategy.
The javax.persistence.loadgraph query hint can be specified as follows:
Unlike JPA, Hibernate offers multiple query hints you can use to customize the execution of a given query. To simplify the way you have to reference a given query hint, Hibernate offers the QueryHints class that looks as follows:
The Hibernate query hints defined by the QueryHints class can be summarized as follows:
Query hint name
QueryHints constant
Description
org.hibernate.cacheMode
CACHE_MODE
Equivalent to setCacheMode method of org.hibernate.query.Query
org.hibernate.cacheRegion
CACHE_REGION
Equivalent to setCacheRegion method of org.hibernate.query.Query
org.hibernate.cacheable
CACHEABLE
Equivalent to setCacheable method of org.hibernate.query.Query
org.hibernate.callable
CALLABLE
Useful for named queries that need to be executed using a JDBC CallableStatement
org.hibernate.comment
COMMENT
Equivalent to setComment method of org.hibernate.query.Query
org.hibernate.fetchSize
FETCH_SIZE
Equivalent to setFetchSizemethod of org.hibernate.query.Query
org.hibernate.flushMode
FLUSH_MODE
Equivalent to setFlushMode method of org.hibernate.query.Query
hibernate.query.followOnLocking
FOLLOW_ON_LOCKING
Override the useFollowOnLocking method of org.hibernate.dialect.Dialect
org.hibernate.lockMode
NATIVE_LOCKMODE
Specify a custom javax.persistence.LockModeType or org.hibernate.LockMode for the current query
hibernate.query.passDistinctThrough
PASS_DISTINCT_THROUGH
Prevent the JPQL or Criteria API DISTINCT keyword from being passed to the SQL query
org.hibernate.readOnly
READ_ONLY
Equivalent to setReadOnly of org.hibernate.query.Query
org.hibernate.timeout
TIMEOUT_HIBERNATE
Equivalent to setTimeout of org.hibernate.query.Query. The timout value is specified in seconds.
javax.persistence.query.timeout
TIMEOUT_JPA
Equivalent to setTimeout of org.hibernate.query.Query. The timout value is specified in milliseconds.
Although you can customize the query execution using the Hibernate-specific query interfaces (e.g. org.hibernate.query.Query), if you’re using the JPA java.persistence.Query interface, you don’t have to unwrap it to get access to the aforementioned query customization options since you can just use the equivalent Hibernate query hint.
Therefore, to fetch the Post entities in read-only mode, you just have to use the org.hibernate.readOnly query hint, as in the following example:
List<Post> posts = entityManager
.createQuery(
"select p " +
"from Post p", Post.class)
.setHint(QueryHints.READ_ONLY, true)
.getResultList();
The hibernate.query.passDistinctThrough query hint is the only way you can prevent the JPQL DISTINCT keyword from being pushed to the associated SQL query.
Online Workshops
If you enjoyed this article, I bet you are going to love my upcoming Online Workshops.
The JPA query hints mechanism allows you to customize the way a given query is executed by Hibernate. For instance, you can specify a timeout threshold or specify that the returned entities should be fetched in read-only mode.
3 Comments on “A beginner’s guide to JPA and Hibernate query hints”
Do query hints like fetch size also work for Criteria API? Looking at the source Hibernate code it seems like it, confirmation would be nice.
I think through JPA, setting fetch size is hardly ever used which is unfortunate because it can provide a nice performance improvement.
Do query hints like fetch size also work for Criteria API? Looking at the source Hibernate code it seems like it, confirmation would be nice.
I think through JPA, setting fetch size is hardly ever used which is unfortunate because it can provide a nice performance improvement.
I think they should since Criteria API simply compiles to JPQL and thd execution is identical to a JPQL query.
Thanks! That’s what I thought.