如何使用JPA Criteria API查询作为考官的Tutor及其关联Schedule
使用JPA Criteria API查询Tutor并获取其作为考官的Schedule列表
场景1:查询指定Tutor,单独获取其作为考官的Schedule列表
这种方式分两次查询,先定位目标Tutor,再查询该Tutor担任考官的所有Schedule:
// 获取EntityManager实例 EntityManager em = ...; CriteriaBuilder cb = em.getCriteriaBuilder(); // 1. 查询目标Tutor CriteriaQuery<Tutor> tutorQuery = cb.createQuery(Tutor.class); Root<Tutor> tutorRoot = tutorQuery.from(Tutor.class); // 替换为实际查询条件,比如根据ID筛选 tutorQuery.where(cb.equal(tutorRoot.get("id"), 1L)); Tutor targetTutor = em.createQuery(tutorQuery).getSingleResult(); // 2. 查询该Tutor作为考官的Schedule列表 CriteriaQuery<Schedule> scheduleQuery = cb.createQuery(Schedule.class); Root<Schedule> scheduleRoot = scheduleQuery.from(Schedule.class); // 关联Schedule的examiners属性 Join<Schedule, Tutor> examinersJoin = scheduleRoot.join("examiners"); // 筛选出examiners为目标Tutor的记录 scheduleQuery.where(cb.equal(examinersJoin.get("id"), targetTutor.getId())); List<Schedule> examinerSchedules = em.createQuery(scheduleQuery).getResultList();
场景2:一次查询返回包含Tutor和对应考官Schedule的DTO
如果希望通过单次查询获取封装好的结果,可以构造DTO来整合数据:
第一步:定义DTO类
public class TutorExaminerInfo { private Tutor tutor; private List<Schedule> examinerSchedules; // 注意:构造方法参数顺序需与查询select的顺序一致 public TutorExaminerInfo(Tutor tutor, List<Schedule> examinerSchedules) { this.tutor = tutor; this.examinerSchedules = examinerSchedules; } // 可选:添加getter/setter方法 }
第二步:使用Criteria API构造查询
EntityManager em = ...; CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<TutorExaminerInfo> query = cb.createQuery(TutorExaminerInfo.class); Root<Tutor> tutorRoot = query.from(Tutor.class); // 创建子查询,获取当前Tutor作为考官的所有Schedule Subquery<List<Schedule>> scheduleSubquery = query.subquery(List.class); Root<Schedule> scheduleSubRoot = scheduleSubquery.from(Schedule.class); scheduleSubquery.select(cb.selectList(scheduleSubRoot)) .where(cb.isMember(tutorRoot, scheduleSubRoot.get("examiners"))); // 构造DTO实例,传入Tutor和子查询结果 query.select(cb.construct(TutorExaminerInfo.class, tutorRoot, scheduleSubquery)) // 替换为实际查询条件 .where(cb.equal(tutorRoot.get("id"), 1L)); TutorExaminerInfo result = em.createQuery(query).getSingleResult();
注意事项
- 建议使用JPA元模型(如
Tutor_、Schedule_)替代硬编码的属性名(如"id"、"examiners"),避免因属性名变更引发错误。 - 若需查询所有Tutor并附带各自的考官Schedule列表,只需移除查询中的
where子句,调用getResultList()即可批量获取结果。
内容的提问来源于stack exchange,提问作者basamoahjnr
相关产品推荐
相关产品推荐

