2014-01-29 52 views
0

我正在使用EclipseLink和MySQL。我試圖從Room實體中檢索一個值,但不加入它。JPQL非連接查詢

這是我在我的日程表實體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(); 
     } 
    } 

這是我的計劃實體:

@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 + " ]"; 
    } 

} 

我是不是做錯了?

回答

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))" 
1

有問題的「r.id <> s.room.id」子句是,使用「s.room.id」導致時間表和室之間的內連接。您可以嘗試使用「r <> s.room」來避免加入,但我認爲這不會對您看起來會有所幫助。 查詢將在同一查詢中使房間和計劃未加入,從而導致笛卡爾連接 - 計劃中的N行乘以計劃中的M行得到返回,然後篩選出幾個與r.id匹配的數據行。 .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))"