JPQL非连接查询

时间:2014-01-29 10:33:21

标签: mysql jpa eclipselink jpql

我正在使用EclipseLink和MySQL。我试图从Room实体中检索一个值而不加入它。

这是我的Schedule实体上的NamedQuery:

@NamedQuery(name = "Schedule.findUnusedRoomForCourseLectureOnly",
query = "SELECT r FROM Schedule s, Room r WHERE s.day = :sday AND (:stime NOT BETWEEN s.startTime AND s.endTime) AND r.id <> s.room.id")

我从JPA控制器获取空值。

这是控制器的代码:

    public Room findUnusedRoomForCourseLectureOnly(int day, Calendar startTime) {
        EntityManager em = getEntityManager();
        Query q = em.createNamedQuery("Schedule.findUnusedRoomForCourseLectureOnly")

                .setParameter("sday", day)
                .setParameter("stime", startTime);
        q.setMaxResults(1);
        try {
            return (Room) q.getResultList().get(0);
        } catch (IndexOutOfBoundsException e) {
            return null;
        } finally {
            em.close();
        }
    }

这是我的Schedule实体:

@Entity    
public class Schedule implements Serializable, Comparable<Schedule> {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(name = "scheduledDay")
    private int day;
    @Temporal(javax.persistence.TemporalType.TIME)
    private Calendar startTime; // 24 hr format
    @Temporal(javax.persistence.TemporalType.TIME)
    private Calendar endTime; // 24 hr format

    @ManyToOne
    private Faculty faculty;

    @ManyToOne
    private Room room;

    @ManyToOne
    private Subject subject;

    private boolean lab;

    @ManyToOne
    private Section section;

    public Schedule() {
        this.startTime = Calendar.getInstance();
        this.endTime = Calendar.getInstance();
    }

    public Schedule(int day, Calendar startTime, Calendar endTime, Faculty faculty, Room room, Subject subject, boolean lab, Section section) {
        this.day = day;
        this.startTime = startTime;
        this.endTime = endTime;
        this.faculty = faculty;
        this.room = room;
        this.subject = subject;
        this.lab = lab;
        this.section = section;
    }

    public Long getId() {
        return id;
    }

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

    public int getDay() {
        return day;
    }

    public void setDay(int day) {
        this.day = day;
    }

    public Calendar getStartTime() {
        return startTime;
    }

    public final void setStartTime(int hour) {
        this.startTime.set(Calendar.HOUR_OF_DAY, hour);
        this.startTime.set(Calendar.MINUTE, 0);
        this.startTime.set(Calendar.SECOND, 0);
    }

    public Calendar getEndTime() {
        return endTime;
    }

    public final void setEndTime(int hour) {
        this.endTime.set(Calendar.HOUR_OF_DAY, hour);
        this.endTime.set(Calendar.MINUTE, 0);
        this.endTime.set(Calendar.SECOND, 0);
    }

    public Faculty getFaculty() {
        return faculty;
    }

    public void setFaculty(Faculty faculty) {
        this.faculty = faculty;
    }

    public Room getRoom() {
        return room;
    }

    public void setRoom(Room room) {
        this.room = room;
    }

    public Subject getSubject() {
        return subject;
    }

    public void setSubject(Subject subject) {
        this.subject = subject;
    }

    public Section getSection() {
        return section;
    }

    public void setSection(Section section) {
        this.section = section;
    }

    public boolean isLab() {
        return lab;
    }

    public void setLab(boolean lab) {
        this.lab = lab;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Schedule)) {
            return false;
        }
        Schedule other = (Schedule) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "ph.edu.bulsusc.planner.entity.Schedule[ id=" + id + " ]";
    }

    @Override
    public int compareTo(Schedule schedule) {
        // return
        // -1 ahead
        // 0 overlapping
        // 1 behind
//        int timeComparison = compareTime(schedule);
//        boolean isTimeConflict = timeComparison == 0;
//
//        if (this.room.getId() == schedule.getRoom().getId() && !isTimeConflict) {
//            // if they have same room and time is not conflict
//            return timeComparison;
//        } else {
//            // same room; time conflict
//            return 0;
//        }
        throw new UnsupportedOperationException("Not implemented yet.");
    }

//    private int compareTime(Schedule schedule) {
//        if (this.day.compareTo(schedule.getDay()) < 0) { // ahead/before of scheduled day
//            return -1;
//        } else if (this.day.compareTo(schedule.getDay()) == 0) { // overlapping day
//            if (this.endTime.get(Calendar.HOUR_OF_DAY) < schedule.getStartTime().get(Calendar.HOUR_OF_DAY)) {
//                return -1;
//            } else if (this.startTime.get(Calendar.HOUR_OF_DAY) > schedule.getEndTime().get(Calendar.HOUR_OF_DAY)) {
//                return 1;
//            } else {
//                return 0;
//            }
//        } else { // behind/after of scheduled day
//            return 1;
//        }
//    }

}

这是我的房间实体:

@Entity
public class Room implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String number;
    private boolean lab;
    @OneToMany
    private List<Course> prioritizedCourses;
    @OneToMany
    private List<Subject> prioritizedSubjects;

    public Room() {
    }

    public Room(String number, boolean lab) {
        this.number = number;
        this.lab = lab;
    }

    public Room(String number, boolean lab, List<Course> prioritizedCourses, List<Subject> prioritizedSubjects) {
        this.number = number;
        this.lab = lab;
        this.prioritizedCourses = prioritizedCourses;
        this.prioritizedSubjects = prioritizedSubjects;
    }

    public Long getId() {
        return id;
    }

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

    public boolean isLab() {
        return lab;
    }

    public void setLab(boolean lab) {
        this.lab = lab;
    }

    public List<Course> getPrioritizedCourses() {
        return prioritizedCourses;
    }

    public void setPrioritizedCourses(List<Course> prioritizedCourses) {
        this.prioritizedCourses = prioritizedCourses;
    }

    public List<Subject> getPrioritizedSubjects() {
        return prioritizedSubjects;
    }

    public void setPrioritizedSubjects(List<Subject> prioritizedSubjects) {
        this.prioritizedSubjects = prioritizedSubjects;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

//    public List<Schedule> getSchedules() {
//        return schedules;
//    }
//
//    /**
//     * Rewrites schedule with this method
//     * @param schedules
//     */
//    public void setSchedules(List<Schedule> schedules) {
//        this.schedules = schedules;
//    }
    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Room)) {
            return false;
        }
        Room other = (Room) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "ph.edu.bulsusc.planner.entity.Room[ id=" + id + " ]";
    }

}

我做错了吗?

2 个答案:

答案 0 :(得分:1)

“r.id&lt;&gt; s.room.id”子句的问题是使用“s.room.id”导致日程安排和房间之间的内部联接。您可以尝试使用“r&lt;&gt; s.room”来避免加入,但我认为它不会对您的目标有所帮助。 查询将在同一查询中取消连接Room和Schedule,导致笛卡尔联接 - 计划中的N行乘以Schedule get中的M行返回,然后过滤掉一些将与r.id&lt;&gt;匹配的行。 s.room.id条款。因此,如果您有多个时间表,将返回所有房间。

您可能希望使用不存在的子查询的ontop。类似的东西:

"SELECT r FROM Room r WHERE not exists (SELECT s from Schedule s where :stime NOT BETWEEN s.startTime AND s.endTime) AND r = s.room))"

答案 1 :(得分:0)

这个JPQL查询对我有用。刚刚对此answer进行了一些修改。

"SELECT r FROM Room r WHERE r.id NOT IN (SELECT s.room.id FROM Schedule s WHERE s.day = :sday AND (:stime BETWEEN s.startTime AND s.endTime))"