Skip to content

Text block queries are stored twice in hibernate HQL interpretation cache #4034

@mdaul-tgtg

Description

@mdaul-tgtg

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.resolveQuery could sanitize the query string that is read from the annotation.
  • Apply the QueryRewriter to the validated query in the SimpleJpaQuery constructor. Then we could write our own query rewriter that sanitizes the block, while the default behaviour with IdentityQueryRewriter would not change.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions