TV Nath
TV Nath

Reputation: 490

Hibernate criteria filter by related entity

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

Upvotes: 4

Views: 14023

Answers (2)

shailesh kodulkar
shailesh kodulkar

Reputation: 13

type mismatch: cannot convert from cascadetype to cascadetype[]

Answer is:

import javax.persistence.CascadeType;

import this line

Upvotes: 0

perissf
perissf

Reputation: 16273

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.

Upvotes: 6

Related Questions