在嵌套字段上使用 WHERE 的 JPQL 查询

Posted

技术标签:

【中文标题】在嵌套字段上使用 WHERE 的 JPQL 查询【英文标题】:JPQL query with WHERE on nested fields 【发布时间】:2013-09-13 09:12:19 【问题描述】:

我有一个带有事件列表的 java 实体类 UserBean:

@OneToMany
private List<EventBean> events;

EventBean 有 Date 变量:

@Temporal(javax.persistence.TemporalType.TIMESTAMP)
private Date eventDate;

现在在 UserBean 中,我想创建一个 NamedQuery,它返回特定范围内的所有日期:

@NamedQuery(name="User.findEventsWithinDates",
            query="SELECT u.events FROM UserBean u WHERE u.name = :name AND u.events.eventDate > :startDate AND u.events.eventDate < :endDate")

上述查询无法编译。我收到此错误:

The state field path 'u.events.eventDate' cannot be resolved to a valid type.

顺便说一下,我使用的是 EclipseLink 版本 2.5.0.v20130507-3faac2b。

我可以做些什么来使这个查询工作?谢谢。

【问题讨论】:

【参考方案1】:

Path u.events.eventDate 是 JPQL 中的非法构造,因为它不允许通过集合值路径表达式导航。在这种情况下,u.events 是一个集合值路径表达式。在 JPA 2.0 规范中,这是用以下词语来说明的:

从路径组成路径表达式在语法上是非法的 计算结果为集合的表达式。例如,如果 指定Order,路径表达式o.lineItems.product是非法的 因为导航到 lineItems 会产生一个集合。这个案例 验证查询字符串时应该会产生错误。处理 这样的导航,必须在 FROM 子句覆盖 lineItems 集合的元素。

这个问题可以通过JOIN来解决:

SELECT distinct(u) 
FROM UserBean u JOIN u.events e 
WHERE u.name = :someName
      AND e.eventDate > :startDate 
      AND e.eventDate < :endDate

【讨论】:

谢谢你的作品!我只想选择具有特定名称的用户。所以我想如果我在 JOIN 语句之前添加 'WHERE u.name = :name' 就可以了。我得到了这个错误:表达式不是有效的条件表达式。按名称选择用户的有效条件表达式是什么? 添加 :name 来回答。这样的条件适用于现有的 WHERE 子句——在 JOIN 语句之前不可能有额外的 WHERE 子句。 是的,做到了。最后的查询: SELECT DISTINCT u.events FROM UserBean u JOIN u.events e WHERE u.name = :name AND e.eventDate > :startDate AND e.eventDate 为什么这里需要 distinct?

以上是关于在嵌套字段上使用 WHERE 的 JPQL 查询的主要内容,如果未能解决你的问题,请参考以下文章

SQL,HQL,CQL,JPQL了解

JPQL查询where子句使用IN,如何将参数传递给查询

使 JPQL/QueryDSL 不会产生可怕的查询

JPQL 更新查询如何处理@Version 字段?

oracle嵌套where查询

在sql中对不相关嵌套查询的处理原则