mysql - JPQL非连接查询

标签 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 Controller 获取空值。

这是 Controller 的代码:

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

}

我做错了吗?

最佳答案

“r.id <> s.room.id”子句的问题是使用“s.room.id”会导致 Schedule 和 Room 之间的内部联接。您可以尝试使用“r <> s.room”来避免加入,但我认为这对您所追求的目标没有帮助。 该查询将在同一查询中将 Room 和 Schedule 分开,从而导致笛卡尔连接 - 返回 Schedule 中的 N 行乘以 Schedule 中的 M 行,然后过滤掉一些与 r.id <> s.room 匹配的行。 id 子句。因此,如果您有多个时间表,所有房间都将被退回。

您可能希望在子查询之上使用不存在。像这样:

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

关于mysql - JPQL非连接查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21428357/

相关文章:

java - 在运行时创建 Spring JPA 实体

eclipse - Eclipse JPA项目(eclipselink,derby)— “create tables from entities”在模式中生成表。不适用于SELECT * FROM TABLE_NAME;

mysql - 使用返回值作为 CSV 的 SELECT IN 查询

MySQL 根据选择的结果更新表

java - 将实体及其所有相关实体保存在 spring boot 的单个保存中

java - 来自数据库的多语言支持数据

mysql - 尝试在 Node js 中运行简单程序时出错

php - 在 INSERT ON DUPLICATE KEY UPDATE 中,检测指定插入值时是否使用默认值

jakarta-ee - WebLogic Server 10.3.6 中的 JPA 2.0

hibernate - 在 EclipseLink 中映射列名和表名