如何在休眠状态下创建相关子查询

时间:2019-02-01 11:35:29

标签: java hibernate java-8

我试图在休眠状态下使用criteria创建一个相关查询。

下面是代码:

预期的sql查询:

select * from 
COLLEGE c
where (select count(s.college_id) from student s where c.college_id = s.college_id group by s.college_id)> 2;

但是它正在生成,外部学院( college0 _ )和子查询学院( college2_ <之间存在 加入的条件/ strong>)

SELECT 
    college0_.COLLEGE_ID AS COLLEGE_1_2_,
    college0_.NAME AS NAME2_2_
FROM
    COLLEGE college0_
WHERE
    (SELECT 
            COUNT(student1_.COLLEGE_ID)
        FROM
            STUDENT student1_
                INNER JOIN
            COLLEGE college2_ ON student1_.COLLEGE_ID = college2_.COLLEGE_ID
        GROUP BY college2_.COLLEGE_ID) >= 3

执行相同操作的方法:

public List<College> findCollegesWithMoreThanXStudentsUsingCriteriaJpa(long x){

        Session session = getSession();



        CriteriaBuilder cb = session.getCriteriaBuilder();

        String hql = " from College c where (select count(s.college) from Student s join s.college c1 where c.id = c1.id group by s.college) > :cnt"; // I am trying the same query using criteria


        CriteriaQuery<College> collegeCriteriaQuery = cb.createQuery(College.class);

        Root<College> collegeRoot = collegeCriteriaQuery.from(College.class);

        collegeCriteriaQuery.select(collegeRoot);


        Subquery<Long> subquery = collegeCriteriaQuery.subquery(Long.class);
        Root<Student> studentRoot = subquery.from(Student.class);
        subquery.select(cb.count(studentRoot.get("college")));
        Join<College,Student> studentCollegeJoin = studentRoot.join("college");


        subquery.correlate(collegeRoot);
        subquery.groupBy(studentCollegeJoin.get("id"));

        collegeCriteriaQuery.where(cb.greaterThanOrEqualTo(subquery,x));


        return session.createQuery(collegeCriteriaQuery).getResultList();

    }

实体类:

Student.java

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import java.util.List;

@Entity
@Table(name = "STUDENT")
public class Student {

    @Id
    @Column(name = "STUDENT_ID")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @Column(name="NAME")
    private String name;

    @ManyToOne
    @JoinColumn(name = "COLLEGE_ID",referencedColumnName = "COLLEGE_ID")
    private College college;


    @OneToMany(cascade = {CascadeType.ALL})
    @JoinColumn(name = "STUDENT_ID",referencedColumnName = "STUDENT_ID")
    private List<StudentAddress> studentAddresses;

    public int getId() {
        return id;
    }

    public Student setId(int id) {
        this.id = id;
        return this;
    }

    public String getName() {
        return name;
    }

    public Student setName(String name) {
        this.name = name;
        return this;
    }

    public College getCollege() {
        return college;
    }

    public Student setCollege(College college) {
        this.college = college;
        return this;
    }

    public List<StudentAddress> getStudentAddresses() {
        return studentAddresses;
    }

    public Student setStudentAddresses(List<StudentAddress> studentAddresses) {
        this.studentAddresses = studentAddresses;
        return this;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", college=" + college +
                ", studentAddresses=" + studentAddresses +
                '}';
    }

}

College.java

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "COLLEGE")
public class College {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "COLLEGE_ID")
    private int id;

    @Column(name = "NAME")
    private String name;


    public int getId() {
        return id;
    }

    public College setId(int id) {
        this.id = id;
        return this;
    }

    public String getName() {
        return name;
    }

    public College setName(String name) {
        this.name = name;
        return this;
    }

    @Override
    public String toString() {
        return "College{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

1 个答案:

答案 0 :(得分:2)

这里不需要correlate,因为这里没有使用外部查询的任何值。您需要的是将子查询与外部查询结合起来

subquery.where(cb.equal(collegeRoot.get("id"), studentCollegeJoin.get("id")));