-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
Given:
A text block query in a JPA repository, which does not use pagination:
@Repository
class MyRepository extends JpaRepository<MyObject, Long> {
@Query("""
SELECT SUM(o.amount)
FROM MyObject o
WHERE o.userId = :userId""")
Optional<Long> sumAmountByUserId(Long userId);
}
Then:
On application startup, when the repository bean is initialized, the query is validated, which includes HQL interpretation. It is stored in hibernate's QueryInterpretationCacheStandardImpl.hqlInterpretationCache with the raw query as cache key, including spaces and line breaks: "SELECT SUM(o.amount)\nFROM MyObject o\nWHERE o.userId = :userId".
On the first execution of the query, it is rewritten to include the pagination and the resulting HQL is interpreted. The rewritten query is identical to the original since there is no additional order clause from pagination, however, UnsortedCachingQuerySortRewriter removes extra spaces and line breaks. That means that QueryInterpretationCacheStandardImpl does not recognize the existing query in the interpretation cache, it parses HQL again and stores it with the new cache key "SELECT SUM(o.amount) FROM MyObject o WHERE o.userId = :userId".
While this is not preventing the query from being executed properly, this is inefficient.
Possible solutions:
- Sanitize the query before validation on startup. For example,
JpaQueryLookupStrategy.resolveQuerycould sanitize the query string that is read from the annotation. - Apply the
QueryRewriterto the validated query in theSimpleJpaQueryconstructor. Then we could write our own query rewriter that sanitizes the block, while the default behaviour withIdentityQueryRewriterwould not change.