Преобразование SQL-запроса в режим гибернации CriteriaQuery

#java #hibernate #hibernate-criteria #criteriaquery

Вопрос:

Я хотел бы преобразовать его, чтобы использовать критерии javax.persistence..Создатель критериев, но не уверен, что делать, любая помощь очень ценится!

SELECT * FROM User u INNER JOIN Teacher t ON t.emp_id = u.emp_id WHERE u.college_id=:college_id AND u.Book.sub_code=:sub_code AND t.lang=:lang

Ответ №1:

Извлечение менеджера сущностей зависит от вашей платформы и вашего варианта использования. Решение предполагает , что у вас есть collegeId , subCode и lang как указано в вашем методе.

Вы создаете запрос для User того, что у вас есть в вашем SELECT , и создаете Root для этого класса.

 CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<User> cq = cb.createQuery(User.class);
Root<User> root = cq.from(User.class);
 

Затем вы присоединяетесь к разным классам. Поскольку я предполагаю, что Book это также необходимый класс, я бы тоже присоединился к этому. Вам не нужно указывать, с каким идентификатором должны происходить соединения, потому что вы уже упомянули, какое значение является идентификатором с аннотацией @Id .

 Join<User, Teacher> teacherJoin = root.join(User_.TEACHER);
Join<User, Book> bookJoin = root.join(User_.BOOK);
 

Различные WHERE условия могут быть добавлены в запрос критериев. Чтобы связать несколько WHERE условий, я добавляю условия в список (чтобы в конечном итоге объединить их).

 List<Predicate> predicates = new ArrayList<>();
predicates.add(cb.equal(root.get(User_.COLLEGE_ID), collegeId));
predicates.add(cb.equal(bookJoin.get(Book_.SUB_CODE), subCode));
predicates.add(cb.equal(teacherJoin.get(Teacher_.LANG), lang));
 

В конце концов, вам придется выполнить созданный запрос.

 cq
    .select(root)
    .where(cb.and(predicates.toArray()));

return entityManager.createQuery(cq).getResultList();
 

В приведенном выше ответе используется генератор метамоделей JPA, чтобы вы не вводили свои фактические ссылочные имена в виде строк. Например, вызов User_.TEACHER дает вам фактическую строку, которая ссылается на Teacher объект внутри User .

В следующем примере показаны приведенные выше фрагменты кода, объединенные в функцию.

 public List<User> findAllByCollegeIdAndBookSubCodeAndTeacherLang(
        String collegeId,
        int subCode,
        Lang lang) {
    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
    CriteriaQuery<User> cq = cb.createQuery(User.class);
    Root<User> root = cq.from(User.class);
    Join<User, Teacher> teacherJoin = root.join(User_.TEACHER);
    Join<User, Book> bookJoin = root.join(User_.BOOK);
    
    List<Predicate> predicates = new ArrayList<>();
    predicates.add(cb.equal(root.get(User_.COLLEGE_ID), collegeId));
    predicates.add(cb.equal(bookJoin.get(Book_.SUB_CODE), subCode));
    predicates.add(cb.equal(teacherJoin.get(Teacher_.LANG), lang));
    
    cq
        .select(root)
        .where(cb.and(predicates.toArray()));

    return entityManager.createQuery(cq).getResultList();
}