带有内部 SELECT 语句的 JPA Criteria Builder 查询
JPA Criteria Builder query with inner SELECT statement
我需要使用 JPA 条件生成器创建以下 SQL 连接条件,
SELECT * FROM student s1
INNER JOIN
(SELECT subject,teacher,MIN(marks) AS marks FROM student GROUP BY subject, teacher) s2
ON s1.subject = s2.subject
AND s1.teacher = s2.teacher
AND s1.marks = s2.marks
下面是实体 class 和 JPA 查询生成器。
@Entity
@JsonIgnoreProperties(ignoreUnknown = true)
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name="id")
Long id;
@Column(name="name")
String name;
@Column(name="subject")
public
String subject;
@Column(name="teacher")
String teacher;
@Column(name="marks")
String marks;
@JsonIgnore
@ManyToOne
@JoinColumns({
@JoinColumn(insertable=false, updatable=false, name="subject",referencedColumnName="subject"),
@JoinColumn(insertable=false, updatable=false, name="teacher",referencedColumnName="teacher"),
@JoinColumn(insertable=false, updatable=false, name="marks",referencedColumnName="marks")
})
Student studentSelf;
@JsonIgnore
@OneToMany(cascade = CascadeType.ALL, mappedBy="studentSelf")
Set<Student> studentref;
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Student> query = cb.createQuery(Student.class);
Root<Student> mainStudent = query.from(Student.class);
List<Predicate> predicates = new ArrayList<>();
Join<Student, Student> studentJoin = mainStudent.join("studentSelf", JoinType.INNER);
List<Student> list = entityManager.createQuery(query).getResultList();
我可以使用连接条件构建查询,但无法创建内部 SELECT 查询。我如何为连接子句创建内部 select 查询?
需求说明: 下面是需要的输入table和输出
我还没有尝试过这个,它云失败了,但有一个例外。但是你能试一试吗?
删除 studentSelf
和 studentRef
如果您只是为此查询添加了它们。 @ManyToOneon
studentSelf` 也不是,因为它会指向许多记录
我认为以下查询等同于您要实现的目标。
SELECT *
FROM student s1
WHERE s1.marks
IN
(
SELECT MIN(s2.marks)
FROM student s2
where s1.subject = s2.subject
AND s1.teacher = s2.teacher
)
- 然后我试着把它翻译成
CriteriaQuery
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Student> query = cb.createQuery(Student.class);
Root<Student> mainStudent = query.from(Student.class);
Subquery<Student> subQuery = query.subquery(Student.class);
Root<Student> subQueryRoot = subQuery.from(Student.class);
Predicate predicate1 = cb.equal(mainStudent.get("teacher"),
subQueryRoot.get("teacher"));
Predicate predicate2 = cb.equal(mainStudent.get("subject"),
subQueryRoot.get("subject"));
Predicate finalPredicate = cb.and(predicate1, predicate2);
subQuery.select(cb.min(subQueryRoot.get("marks"))).where(finalPredicate);
query.select(mainStudent).where(mainStudent.get("marks").in(subQuery));
em.createQuery(issueQuery).getResultList();
更新
已根据 vinay-s-g
条评论
将 subquery.correlate(mainStudent);
更新为 subQuery.from(Student.class);
对上述答案进行了细微修改,
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Student> query = cb.createQuery(Student.class);
Root<Student> mainStudent = query.from(Student.class);
Subquery<Student> subQuery = query.subquery(Student.class);
Root subQueryRoot = subQuery.from(Student.class);
Predicate predicate1 = cb.equal(mainStudent.get("teacher"),
subQueryRoot.get("teacher"));
Predicate predicate2 = cb.equal(mainStudent.get("subject"),
subQueryRoot.get("subject"));
Predicate finalPredicate = cb.and(predicate1, predicate2);
subQuery.select(cb.min(subQueryRoot.get("marks"))).where(finalPredicate);
query.select(mainStudent).where(mainStudent.get("marks").in(subQuery));
return entityManager.createQuery(query).getResultList();
我需要使用 JPA 条件生成器创建以下 SQL 连接条件,
SELECT * FROM student s1
INNER JOIN
(SELECT subject,teacher,MIN(marks) AS marks FROM student GROUP BY subject, teacher) s2
ON s1.subject = s2.subject
AND s1.teacher = s2.teacher
AND s1.marks = s2.marks
下面是实体 class 和 JPA 查询生成器。
@Entity
@JsonIgnoreProperties(ignoreUnknown = true)
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name="id")
Long id;
@Column(name="name")
String name;
@Column(name="subject")
public
String subject;
@Column(name="teacher")
String teacher;
@Column(name="marks")
String marks;
@JsonIgnore
@ManyToOne
@JoinColumns({
@JoinColumn(insertable=false, updatable=false, name="subject",referencedColumnName="subject"),
@JoinColumn(insertable=false, updatable=false, name="teacher",referencedColumnName="teacher"),
@JoinColumn(insertable=false, updatable=false, name="marks",referencedColumnName="marks")
})
Student studentSelf;
@JsonIgnore
@OneToMany(cascade = CascadeType.ALL, mappedBy="studentSelf")
Set<Student> studentref;
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Student> query = cb.createQuery(Student.class);
Root<Student> mainStudent = query.from(Student.class);
List<Predicate> predicates = new ArrayList<>();
Join<Student, Student> studentJoin = mainStudent.join("studentSelf", JoinType.INNER);
List<Student> list = entityManager.createQuery(query).getResultList();
我可以使用连接条件构建查询,但无法创建内部 SELECT 查询。我如何为连接子句创建内部 select 查询?
需求说明: 下面是需要的输入table和输出
我还没有尝试过这个,它云失败了,但有一个例外。但是你能试一试吗?
删除
studentSelf
和studentRef
如果您只是为此查询添加了它们。 @ManyToOneon
studentSelf` 也不是,因为它会指向许多记录我认为以下查询等同于您要实现的目标。
SELECT *
FROM student s1
WHERE s1.marks
IN
(
SELECT MIN(s2.marks)
FROM student s2
where s1.subject = s2.subject
AND s1.teacher = s2.teacher
)
- 然后我试着把它翻译成
CriteriaQuery
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Student> query = cb.createQuery(Student.class);
Root<Student> mainStudent = query.from(Student.class);
Subquery<Student> subQuery = query.subquery(Student.class);
Root<Student> subQueryRoot = subQuery.from(Student.class);
Predicate predicate1 = cb.equal(mainStudent.get("teacher"),
subQueryRoot.get("teacher"));
Predicate predicate2 = cb.equal(mainStudent.get("subject"),
subQueryRoot.get("subject"));
Predicate finalPredicate = cb.and(predicate1, predicate2);
subQuery.select(cb.min(subQueryRoot.get("marks"))).where(finalPredicate);
query.select(mainStudent).where(mainStudent.get("marks").in(subQuery));
em.createQuery(issueQuery).getResultList();
更新
已根据 vinay-s-g
条评论
subquery.correlate(mainStudent);
更新为 subQuery.from(Student.class);
对上述答案进行了细微修改,
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Student> query = cb.createQuery(Student.class);
Root<Student> mainStudent = query.from(Student.class);
Subquery<Student> subQuery = query.subquery(Student.class);
Root subQueryRoot = subQuery.from(Student.class);
Predicate predicate1 = cb.equal(mainStudent.get("teacher"),
subQueryRoot.get("teacher"));
Predicate predicate2 = cb.equal(mainStudent.get("subject"),
subQueryRoot.get("subject"));
Predicate finalPredicate = cb.and(predicate1, predicate2);
subQuery.select(cb.min(subQueryRoot.get("marks"))).where(finalPredicate);
query.select(mainStudent).where(mainStudent.get("marks").in(subQuery));
return entityManager.createQuery(query).getResultList();