Problem with translating SQL 'IN' subquery into a JPA Criteria Query

泪湿孤枕 提交于 2020-04-17 22:51:31

问题


I'm trying to translate this SQL query into a JPA Criteria Query:

select distinct student0_.name 
from vnic03.student student0_
where (exists(select teacher0_.social_number
          from vnic03.teacher teacher0_
          where teacher0.social_number = ?
            and teacher0_.school_id in (select school0_.id
                                               from vnic03.school school0_
                                               where school0_.student_id = student0_.id)))  

These are the tables (I have simplified and renamed them for posting them here, in reallity they have several million entries):

Right now I have following code:

CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<String> searchQuery = criteriaBuilder.createQuery(String.class);
Root<Student> root = searchQuery.from(Student.class);
List<Predicate> restrictions = new ArrayList<>();

Subquery<Teacher> subQuery = searchQuery.subquery(Teacher.class);
Root<Teacher> fromSchoolSubQuery = subQuery.from(Teacher.class);
List<Predicate> subRestrictions = new ArrayList<>();

Subquery<School> subQuery2 = searchQuery.subquery(School.class);
Root<School> fromSchoolSubSubQuery = subQuery2.from(School.class);
List<Predicate> subSubRestrictions = new ArrayList<>();

subRestrictions.add(criteriaBuilder.equal(fromSchoolSubQuery.get(Social_number), userInput));
subRestrictions.add(criteriaBuilder.equal(fromSchoolSubQuery.get(School_ID), subQuery2.select(fromSchoolSubSubQuery.get(School_ID)).where(criteriaBuilder.equal(fromSchoolSubSubQuery.get(Student_ID), root.get(student_ID)))));

restrictions.add(criteriaBuilder.exists(subQuery.select(
fromSchoolSubQuery.get(Social_number)).where(
subRestrictions.toArray(new Predicate[0]))));

searchQuery.distinct(true)
            .select(root.get(name))
            .where( restrictions.toArray(new Predicate[restrictions.size()]) );

TypedQuery<String> query = em.createQuery(searchQuery)
List<String> nameList = query.getResultList();

But this translates into:

select distinct student0_.name 
from vnic03.student student0_
where (exists(select teacher0_.social_number
          from vnic03.teacher teacher0_
          where teacher0.social_number = ?
          and teacher0_.school_id = (select school0_.id
                                           from vnic03.school school0_
                                           where school0_.student_id = student0_.id)))

So I just need to replace the = by in in the last and part. I found in other SO questions something like this:

CriteriaBuilder.In<String> in = criteriaBuilder.in( ??? );

or

Path<Object> path = root.get(student_ID);
CriteriaBuilder.In<Object> in = criteriaBuilder.in(path);

but I just don't know how to use it properly...

So if you know how to translate only this part, it would solve it for me probably already:

where teacher0_.school_id **in** (select school0_.id
from vnic03.school school0_
where school0_.student_id = student0_.id))) 

回答1:


I found a Solution after reading chapter 5 in this article: https://www.baeldung.com/jpa-criteria-api-in-expressions

Subquery<School> subQueryForInExpression = searchQuery.subquery(School.class);
Root<School> fromSchoolSubQuery = subQueryForInExpression.from(School.class);

subQueryForInExpression.select(fromSchoolSubQuery.get(student_id)).where(criteriaBuilder.equal(fromSchoolSubQuery.get(school_id), root.get(student_id)));

The subQueryForInExpression represents the Select subquery in the IN Expression:

select school0_.id
from vnic03.school school0_
where school0_.student_id = student0_.id

Now we have to add the in Expression to the subRestrictions, this is done with CriterisBuilder.in(...).value(subQueryForInExpression):

subRestrictions.add(criteriaBuilder.in(fromSchoolSubQuery.get(school_id)).value(subQueryForInExpression));


来源:https://stackoverflow.com/questions/60758439/problem-with-translating-sql-in-subquery-into-a-jpa-criteria-query

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!