I want to execute a query matching a specific subclass property, so I'm trying to use treat()
.
In this example I want:
all subjects with name starting with 'a',
or all subjects, which are persons, with last name starting with 'a'
private List<Subject> q1()
{
CriteriaBuilder b = em.getCriteriaBuilder();
CriteriaQuery<Subject> q = b.createQuery(Subject.class);
Root<Subject> r = q.from(Subject.class);
q.select(r);
q.distinct(true);
q.where(
b.or(
b.like(r.get(Subject_.name), "a%"),
b.like(b.treat(r, Person.class).get(Person_.lastName), "a%")));
return em.createQuery(q).getResultList();
}
Obviously, Person
extends Subject
, Subject
is abstract, inheritance is SINGLE_TABLE
, and (non influent).Subject
has @DiscriminatorOptions(force = true)
for other reasons
But the generated SQL is this:
select distinct subject0_.ID as ID2_71_, subject0_.CODE as CODE3_71_, ...
from SUBJECT subject0_
where subject0_.DTYPE='Person' and (subject0_.name like 'a%' or subject0_.lastName like 'a%')
while I'm expecting:
select distinct subject0_.ID as ID2_71_, subject0_.CODE as CODE3_71_, ...
from SUBJECT subject0_
where subject0_.name like 'a%' or (subject0_.DTYPE='Person' and subject0_.lastName like 'a%')
Is there a way to produce the expected query using criteria builder?
Note that
- using another Root -
q.from(Person.class)
- using subqueries -
q.subquery(Person.class)
- moving lastName field up to Subject
- using Native Queries
- using Entity Graphs
are not acceptable.
I'm interested in something which can be declared and used directly in WHERE clause (produced only from CriteriaBuilder and/or the single Root, just like the treat()
clause), if it does exist.
java.lang.IllegalArgumentException: Unable to locate Attribute with the the given name [inheritedTags] on this ManagedType [...]
. What am I doing wrong? (My subclass is abstract) I really need the answer please help! – Ombre