【问题标题】:JPQL query sometimes not returning expected resultJPQL 查询有时不返回预期结果
【发布时间】:2015-01-09 00:16:35
【问题描述】:

我有一个奇怪的问题,即 JPQL 查询显示了一些不一致的行为。我编写了以下方法,我希望从中获取给定员工的所有活动的列表,这些活动与给定的 TimePeriod 对象重叠。

    public List<Activity> getAllActivities(Employee employee,
        TimePeriod timePeriod) throws DatasetException {
    if (employee == null || timePeriod == null) {
        throw new IllegalArgumentException();
    }
    try {
        final Query query = em
                .createQuery("SELECT DISTINCT a from Activity a INNER JOIN a.employeeTimePeriods e"
                        + " INNER JOIN e.timePeriods t WHERE "
                        + " e.employee = ?1"
                        + " AND a.time.day = ?2"
                        + " AND ?3 < t.endTime"
                        + " AND ?4 > t.startTime"
                        + " ORDER BY a.time.startTime");
        query.setParameter(1, employee);
        query.setParameter(2, timePeriod.getDay());
        query.setParameter(3, timePeriod.getStartTime());
        query.setParameter(4, timePeriod.getEndTime());
        return query.getResultList();
    } catch (Exception e) {
        LOGGER.error(String.format(
                "Exception while getting all activities of employee %s, "
                        + "which overlap time period %s.", employee,
                timePeriod), e);
        throw new DatasetException(
                String.format(
                        "Error while getting all activities of employee %s, "
                                + "which overlap time period %s: "
                                + e.getMessage(), employee, timePeriod));
    }
}

此外,我创建了一些测试用例: 我有一名员工,他参加了两项活动:

  • 每周一 10:00 到 10:45
  • 每周一 10:45 到 11:30

我有一个 TimePeriod 对象,日期设置为星期一,开始时间设置为 10:00,结束时间设置为 12:00。

现在,我希望始终从我的方法中获取先前列出的两个活动,但存在问题。我有时(!)只得到第一个,在其他时候测试用例成功。我有更多这种方法的测试用例,从未失败(但我只是注意到上面的测试用例是唯一的,它必须选择两个活动)。

我也有相同的房间测试用例(除了 TimePeriod 对象的开始时间是 09:00 之外),它从未失败过。但由于查询存在差异 - 在房间查询中我能够使用 MEMBER OF - 我猜测连接可能存在问题。

为了完整起见,房间查询:

            final Query query = em.createQuery("SELECT a FROM Activity a WHERE"
                + " ?1 MEMBER OF a.rooms AND a.time.day = ?2"
                + " AND ?3 < a.time.endTime AND ?4 > a.time.startTime"
                + " ORDER BY a.time.startTime");
        query.setParameter(1, room);
        query.setParameter(2, timePeriod.getDay());
        query.setParameter(3, timePeriod.getStartTime());
        query.setParameter(4, timePeriod.getEndTime());

有人对我的问题有什么建议吗?

【问题讨论】:

  • 尝试打开日志以查看生成的查询和使用的参数:wiki.eclipse.org/EclipseLink/Examples/JPA/Logging 这将有助于确定失败案例与成功案例的不同之处。
  • 谢谢。就是这么做的。两个查询中选择参数的顺序只有一点点不同,但这确实不应该对查询执行产生任何影响。
  • 你能显示在工作案例和非工作案例中与生成的 SQL 相关的参数吗?
  • 我现在也有另一个与活动和员工相关的查询的问题,我完全不知道为什么会发生这种情况。成功和失败情况下的查询看起来几乎一样,只是开头略有不同:成功:SELECT DISTINCT t1.ID, t1.TYPE, t1.DAY, t1.DURATION, t1.ENDTIME, t1.STARTTIME, t1.MEETINGTYPE_ID, t1.PROJECTTYPE_ID, t1.LESSONTYPE_ID --- 失败:SELECT DISTINCT t1.ID, t1.TYPE, t1.DAY, t1.DURATION, t1.ENDTIME, t1.STARTTIME, t1.LESSONTYPE_ID, t1.PROJECTTYPE_ID, t1.MEETINGTYPE_ID

标签: java jpa eclipselink jpql


【解决方案1】:

我不确定为什么您的查询有时会返回错误的结果(对于相同的输入?),但我确实认为您可以简化查询,也许可以更轻松地进行调试。

select
    distinct a
from
    Activity a inner join a.employeeTimePeriods e
    inner join e.timePeriods t
where
    e.employee = ?1 and
    a.time.day = ?2 and
    t.endTime >= ?3 and
    t.startTime <= ?4

其中 ?1 = 房间,?2 = 天,?3 = 开始时间,?4 = 结束时间。

基本上,您要求的是“向我显示特定员工在给定日期的活动,该活动在我的窗口开始之后或之时结束,并在我的窗口结束之前或之时开始。

所以对于您的活动:

  • 活动 1 = 星期一 10:00 到 10:45
  • 活动 2 = 星期一 10:45 到 11:30

而时间段:10:00 到 12:00,它应该返回这两条记录,因为:

  • 活动 1
    • t.endTime 是 10:45,大于 10:00 AND
    • t.startTime 是 10:00 并且在 12:00 之前。
  • 活动 2
    • t.endTime 是 11:30,大于 10:00 AND
    • t.startTime 是 10:45,在 12:00 之前。

【讨论】:

  • 感谢您的建议。看来我想的有点太复杂了,如果没有您的评论,我不会注意到,所以谢谢!它实际上并不能解决有时测试失败的问题,因为我在几次测试运行后不得不注意到。在这个测试用例运行一个 init 方法之前,它总是创建相同的数据库状态。所以是的,它确实为相同的输入返回错误的结果。我已经调试了项目,直到我看到列表大小为 1,中止并查看了数据库。一切看起来都和预期的一样。这很令人困惑......
  • 一点注释:我实际上并不想得到活动,它从窗口结束或在窗口开始结束,所以我使用 来简化查询。
  • 啊,是的,我应该抓住它。很高兴它(有点)有帮助。
猜你喜欢
  • 2014-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多