org.hibernate.Query.getQueryString() does not expose HQL query anymore on Hibernate 6
Description
Activity
Steve Ebersole July 8, 2022 at 4:29 PM
Personally I’d prefer that not get added to JPA specifically for the reason you mentioned - we no longer do that for criteria queries. In fact we only did it previously because of the “hacky” way I had to implement the original criteria support. If it gets added, no big deal - we have that functionality around.
Oliver Drotbohm July 8, 2022 at 3:57 PM
Sure thing. As you already indicated, JPA is not really convenient in that regard. We currently have abstracted the different ways of accessing the query string behind an interface, and Hibernate’s implementation has served us well so far. The Eclipselink implementation, too. And for everything else, we just report to the user that their provider doesn’t support query string extraction. The lookup is a one-time thing on startup and only happening for named queries so that the penalty is acceptable.
I thought about suggesting JPA’s Query
to get a ….getQueryString()
method a couple of times and during the H5 generation, “Hibernate and Eclipselink already have this implemented anyway” would’ve been a good argument in favor of it. Do you think that’d still make sense, even if you’re currently not in a state anymore that has already implemented it (at least not completely)?
With the current state of affairs, we’d have to direct users away from using JPA named queries, which is not the end of the world I guess, but still…
Steve Ebersole July 8, 2022 at 3:30 PM
Well, to be clear, you are already relying on a particular provider’s API by accessing the “query string” at all - that is not defined by JPA.
Not to mention the performance is going to be “horrible” for a criteria as it is (re)calculated every time.
Just some pointers. Up to you how you want to do what you do.
Andrea Boriero July 8, 2022 at 2:08 PM
Thanks , yes I saw the cast happening in SqmDynamicInstantiation
#appendHqlString
()
Oliver Drotbohm July 8, 2022 at 1:39 PM
The inspection of the queries on an instance level is unfortunately only one use case, we need to fall back to the HQL String
from a TypedQuery
. I'll definitely go ahead and review our test cases to rather switch to structural inspection as suggested. When we originally chose this approach, we thought that inspecting the created String
would couple us less to Hibernate's internals than instanceof-checks on the implementation and then traversing the internal query structure, as we kind of expected that you'd consider exactly that structure internal API.
The case in which we need this outside of general testing is when we need to create count query equivalents for user defined named queries. Relying on the HQL string reported for those and augmenting them to eventually create a new TypedQuery
seemed like a reasonable way to achieve that without having to use a particular JPA provider’s API.
Thanks for looking into the ClassCastException
. Did you see the other one around SqmDynamicInstantiation
, that I added to the bullet list below, too?
In Hibernate 5 generation, the implementations of the JPA
Query
interface all implementedorg.hibernate.Query
, which exposed and still exposes a….getQueryString()
method. The Hibernate 6 implementations don't return any HQL from that anymore, but<criteria>
.We have previously used that method in tests to inspect the query setup that we create in Spring Data JPA, whether we flip the distinct flag on under certain conditions etc. It would be nice to still be able to do that on 6 as it seemed to be a way to inspect the arrangement without having to mess with the internals of the actual instance. Happy to consider alternatively suggested approaches, too.