Filter hibernation criteria using a linked object

I have an object that has a collection of related objects.

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. At the moment I was working on how to filter by class ID, but I have no idea how to filter, of course, given that the student has a set of courses and the tables are related. I have read several articles but the code is not the same as the one I already have.

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

      

+3


source to share


2 answers


First of all, there is a bug in your Entity: the annotation JoinColumn

is being applied to the entity on the back of the relationship, Course

in your case.

So, if an object Course

has a property student

, Student has a property like:

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

      

and in the course object you have (it also states that in the db in the course table there is a field called "student":

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

      

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

As for the Criteria Query, since you want to get a list student

S, you can define your CriteriaQuery in a safer way:

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

      

As for the question, you should join the tables like this:

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

      

or, using MetaModel:



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

      

(if the OneToMany property was defined as List

or Collection

, you would have to use the corresponding classes ListJoin

and CollectionJoin

).

in courses, you can apply the conditions you want Predicate

(assume the course object 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, to correctly align the list of predicates, you can use (at least) two methods:

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.

+2


source


Type mismatch: cannot convert from cascadetype to cascadetype []

Answer:



import javax.persistence.CascadeType;

import this line

-1


source







All Articles