javahibernatehibernate-criteriacriteriaquery

Convert SQL Query to Hibernate CriteriaQuery


I'd like to convert it to use the javax.persistence.criteria.CriteriaBuilder, but am unsure what do, any help is much appreciated!

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


Solution

  • The retrieval of the entity manager depends on your framework and your use case. The solution assumes that you have collegeId, subCode and lang as given values in your method.

    You create a query for the User which you have in your SELECT and create a Root for this class.

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

    Then, you join the different classes. As I assume that Book is also a needed class, I would join this as well. You do not have to mention on which ID the joins should happen because you already mentioned which value is the ID with the annotation @Id.

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

    The different WHERE conditions can be added to the criteria query. To link several WHERE conditions, I add the conditions to a list (to eventually combine them).

    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));
    

    Eventually, you have to execute the constructed query.

    cq
        .select(root)
        .where(cb.and(predicates.toArray()));
    
    return entityManager.createQuery(cq).getResultList();
    

    The above answer uses the JPA Metamodel Generator to prevent you from typing your actual reference names as strings. For example, the call User_.TEACHER gives you the actual string which refers to the Teacher object within User.

    The following example shows the above code snippets merged together in a function.

    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();
    }