Hibernate criteria filter by related entity

11,943

First of all, there is an error in your Entity: the JoinColumn annotation applies to the entity on the inverse side of the relationship, Course in your case.

So, if Course entity has a property student, Student has a property like:

@OneToMany(cascade = CascadeType.ALL, mappedBy = "student")
private Set<Course> courses;

and in Course entity you have (here it also states that in the db the table course has a field called "student":

@JoinColumn(name = "student", referencedColumnName = "id")
@ManyToOne(optional = false)
private Student student;

Read this link for an entry-level explaination on how to map entity relationships.

Regarding the Criteria Query, since you want to retrieve a List of StudentS, you can define your CriteriaQuery in a more type safe way:

CriteriaQuery<Student> criteria = criteriaBuilder.createQuery(Student.class);

Regarding the question, you have to join the tables in this way:

SetJoin<Student, Course> courses = root.join("courses");

or, using MetaModel:

SetJoin<Student, Course> courses = root.join(Student_.courses);

(had the OneToMany property been defined as a List or a Collection, you'd have had to use the corresponding ListJoin and CollectionJoin classes).

on the courses you can apply the desired Predicate conditions (supposing that Course entity has a string property called courseName):

Predicate p = criteriaBuilder.equal(courses.get("courseName"), "name-to-look-for");

or, using Metamodel:

Predicate p = criteriaBuilder.equal(courses.get(Course_.courseName), "name-to-look-for");

Finally, in order to concatenate correctly a list of predicates, you can use (at least) two techniques:

Predicate p1 = ...;
Predicate p2 = ...;

criteria.where(criteriaBuilder.and(p1, p2));

or

List<Predicate> conditions = new ArrayList<Predicate> ();
conditions.add(p1);
conditions.add(p2);
criteria.where(conditions.toArray(new Predicate[] {}));

See also this excellent article.

Share:
11,943
TV Nath
Author by

TV Nath

I am a moderate Software Engineer who likes to improve my knowledge in technologies related Java, J2EE, and Javascript. There are a lot of space for me to improve.

Updated on June 26, 2022

Comments

  • TV Nath
    TV Nath almost 2 years

    I have an entity which has a collection of related entities.

    public class Student{
    
    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinColumn(name = "COURSE_STUDENT_ID" , insertable=false,updatable=false)
    private Set <Course> courses;
    

    I want to filter students by course names and student class id. For now I have worked it out how to filter by class id but I have no idea how to filter by courseId given that Student entity has a set of courses and the tables are related. I have read some articles but no code matches the one I have already.

    CriteriaBuilder criteriaBuilder = persistenceStore.createCriteriaBuilder();
    CriteriaQuery<Object> criteria = criteriaBuilder.createQuery();
    Root<Student> root = criteria.from(Student.class);
    List<Predicate> params = new ArrayList<Predicate>();
    
    params.add(criteriaBuilder.equal(root.get("classId"),classId));
    
    Predicate[] predicates = new Predicate[params.size()];
    params.toArray(predicates);
    criteria.select(root);
    criteria.where(criteriaBuilder.and(predicates));
    Query query = persistenceStore.createQuery(criteria);
    List<Student> resultList = query.getResultList();