0

假设我有实体 Lecturer 和 Course 两个实体在 JPA 2.0 中具有多对多关系

像这样工作的非注释实体 LecturerCourse(具有多表选择列,未注释)和 JPQL 是完全可以的。

        final Query query = em.createQuery(
            "select new com.cs.entity.LectureCourse(l.id, l.name, l.surName, " +
                    "l.type, c.code, c.name) from lecturer l join l.courses c where l.id = :l_id"
    );

如何使用 JPA Criteria API 做同样的事情?

这里分别是 Lecturer 和 Courses 的代码

@Entity(name = "course")
public class Course implements Serializable {

    @Id
    @Column(name = "course_code", columnDefinition = "char(6)",
            unique = true, nullable = false)
    private String code;
    @Column(name = "course_name")
    private String name;
    @ManyToMany(mappedBy = "courseSet", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private Set<Student> students;
    @ManyToOne(fetch = FetchType.EAGER, targetEntity = Lecturer.class)
    @JoinColumn(name = "lecture_id")
    private Lecturer lecturer;

    public Course() {
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getName() {
        return name;
    }

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

    public Set<Student> getStudents() {
        return students;
    }

    public void setStudents(Set<Student> students) {
        this.students = students;
    }

    public Lecturer getLecturer() {
        return lecturer;
    }

    public void setLecturer(Lecturer lecturer) {
        this.lecturer = lecturer;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Course)) return false;

        Course course = (Course) o;

        if (code != null ? !code.equals(course.code) : course.code != null) return false;
        if (name != null ? !name.equals(course.name) : course.name != null) return false;
        if (students != null ? !students.equals(course.students) : course.students != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = code != null ? code.hashCode() : 0;
        result = 31 * result + (name != null ? name.hashCode() : 0);
        result = 31 * result + (students != null ? students.hashCode() : 0);
        return result;
    }
}


@Entity(name = "lecturer")
public class Lecturer {

    public static enum LectureType{
        FULL_TIME, PART_TIME
    }

    @Id
    @Column(name = "lecture_id", nullable = false,
            unique = true, columnDefinition = "char(8)")
    private String id;
    @Column(name = "lecture_name", length = 20, nullable = false)
    private String name;
    @Column(name = "lecture_sur_name", length = 20, nullable = false)
    private String surName;
    @Enumerated(EnumType.ORDINAL)
    @Column(name = "lecture_type", columnDefinition = "char(1)")
    private LectureType type;
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "lecturer", fetch = FetchType.EAGER)
    private Set<Course> courses;

    public Lecturer() {
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public String getSurName() {
        return surName;
    }

    public void setSurName(String surName) {
        this.surName = surName;
    }

    public LectureType getType() {
        return type;
    }

    public void setType(LectureType type) {
        this.type = type;
    }

    public Set<Course> getCourses() {
        return courses;
    }

    public void setCourses(Set<Course> courses) {
        this.courses = courses;
        for(final Course course : this.courses){
            course.setLecturer(this);
        }
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Lecturer)) return false;

        Lecturer lecturer = (Lecturer) o;

        if (id != null ? !id.equals(lecturer.id) : lecturer.id != null) return false;
        if (name != null ? !name.equals(lecturer.name) : lecturer.name != null) return false;
        if (surName != null ? !surName.equals(lecturer.surName) : lecturer.surName != null) return false;
        if (type != lecturer.type) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = id != null ? id.hashCode() : 0;
        result = 31 * result + (name != null ? name.hashCode() : 0);
        result = 31 * result + (surName != null ? surName.hashCode() : 0);
        result = 31 * result + (type != null ? type.hashCode() : 0);
        return result;
    }
}
4

1 回答 1

1

What you're looking for is a form of CriteriaQuery#multiselect ... I'm assuming you're generating an appropriate static metamodel (that's where the EntityClass_.field pieces come from) but working by hand I come up with something like:

CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<LectureCourse> criteria = builder.createQuery(LectureCourse.class);
Root<Lecturer> l = criteria.from(Lecturer.class);
Path<Course> c = l.join(Lecturer_.courses);
ParameterExpression<String> l_id = builder.parameter(String.class);
Predicate lecturerIdMatches = builder.equal(l.get(Lecturer_.id),l_id);
TypedQuery<LectureCourse> query = em.createQuery(criteria.multiselect(l.get(Lecturer_.id), l.get(Lecturer_.name), l.get(Lecturer_.surName), l.get(Lecturer_.type), c.get(Course_.code), c.get(Course_.name)).where(lecturerIdMatches));

query.setParameter(l_id,"queryvalue");
List<LectureCourse> results = query.getResultList();
于 2012-12-27T06:26:29.933 回答