按相关实体筛选休眠条件

TV *_*ath 3 java hibernate criteria-api jakarta-ee

我有一个包含相关实体集合的实体。

public class Student{

@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "COURSE_STUDENT_ID" , insertable=false,updatable=false)
private Set <Course> courses;
Run Code Online (Sandbox Code Playgroud)

我想按课程名称和学生班级 ID 过滤学生。现在我已经弄清楚了如何按类 id 过滤,但我不知道如何按 courseId 过滤,因为 Student 实体有一组课程并且表是相关的。我已经阅读了一些文章,但没有任何代码与我已经读过的代码相匹配。

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();
Run Code Online (Sandbox Code Playgroud)

per*_*ssf 5

首先,您的实体中存在错误:在您的情况下JoinColumn,注释适用于关系相反侧的实体Course

所以,如果Courseentity 有一个 property student,Student 有一个类似的属性:

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

并且在您拥有的 Course 实体中(此处它还说明在数据库中,课程表有一个名为“student”的字段:

@JoinColumn(name = "student", referencedColumnName = "id")
@ManyToOne(optional = false)
private Student student;
Run Code Online (Sandbox Code Playgroud)

阅读此链接以获取有关如何映射实体关系的入门级说明。

关于 Criteria Query,由于您想要检索StudentS的 List ,您可以以更安全的方式定义 CriteriaQuery:

CriteriaQuery<Student> criteria = criteriaBuilder.createQuery(Student.class);
Run Code Online (Sandbox Code Playgroud)

关于这个问题,你必须以这种方式加入表格:

SetJoin<Student, Course> courses = root.join("courses");
Run Code Online (Sandbox Code Playgroud)

或者,使用元模型:

SetJoin<Student, Course> courses = root.join(Student_.courses);
Run Code Online (Sandbox Code Playgroud)

(如果 OneToMany 属性被定义为 aList或 a Collection,则必须使用相应的ListJoinandCollectionJoin类)。

在课程上,您可以应用所需的Predicate条件(假设 Course 实体有一个名为 的字符串属性courseName):

Predicate p = criteriaBuilder.equal(courses.get("courseName"), "name-to-look-for");
Run Code Online (Sandbox Code Playgroud)

或者,使用元模型:

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

最后,为了正确连接谓词列表,您可以(至少)使用两种技术:

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

criteria.where(criteriaBuilder.and(p1, p2));
Run Code Online (Sandbox Code Playgroud)

或者

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

另请参阅这篇出色的文章