Hibernate criteria filter by related entity
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 Student
S, 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.
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, 2022Comments
-
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();