我正在使用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 + " ]";
}
}
我做错了吗?
答案 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))"