2014-01-29 3 views
0

Я использую EclipseLink и MySQL. Я пытаюсь извлечь значение из объекта «Комната», не присоединившись к нему.JPQL non join query

Вот мой NamedQuery на моем Schedule лица:

@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 строк в Schedule, будет возвращено, а затем несколько отфильтровываются, что будет соответствовать r.id <> 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))"