I'm working on a Java application that uses Hibernate6 + JPA.
I have classes like
class Thing {
Parent parent
}
class Parent {
}
class ChildA extends Parent {
}
class ChildB extends Parent {
}
I want to be able to write a query like SELECT * FROM Thing JOIN Parent JOIN ChildA
but NOT select any data from ChildB.
I've tried making the parent table use TABLE_PER_CLASS and JOINED inheritance strategies, and write a HQL query like:
SELECT t FROM Thing t
JOIN t.parent p
WHERE
TYPE(p) = ChildA
but this still selects all the child data from ChildA and ChildB, ie: SELECT * FROM Thing Join Parent Join ChildA Join ChildB
...
I could implement a Java Model that uses composition instead, but my situation highly favors inheritance, as it requires many less cascading changes in the code base.
Is there a model and combination of annotations to get Hibernate + JPA to produce the desired query?
I've tried the above model and HQL query, expecting to the ORM to return Thing
with a ChildA
using an efficient query. I get the data I requested, but it creates an inefficient query that asks for more data than I want.
Use "TREAT" instead of type. The JPA (2.1) specification section 4.4.9 states:
If during query execution the first argument to the TREAT operator is not a subtype (proper or improper) of the target type, the path is considered to have no value, and does not participate in the determination of the result. That is, in the case of a join, the referenced object does not participate in the result, and in the case of a restriction, the associated predicate is false. Use of the TREAT operator therefore also has the effect of filtering on the specified type (and its subtypes) as well as performing the downcast.
You should be able to use:
"SELECT t from Thing t JOIN TREAT(t.parent AS ChildA) p"
to return only Things with ChildA parents.