替代在Hibernate中使用“ON子句”获取连接

时间:2014-07-28 21:46:45

标签: java hibernate jpa

给出的是RDBMS中的以下域模型,它与Hibernate映射到Java对象中。

┌─────────┐            ┌─────────────┐
│ Project │ 1     0..n │ UserSetting │
├─────────┼------------┼─────────────┤
│  name   │            │   username  │
└─────────┘            │   favorite  │
                       └─────────────┘

用户可以将项目标记为收藏,并由关联(可选)UserSetting条目反映。 如果用户没有标记项目,则数据库中有UserSetting条目,这意味着项目不是最喜欢的。认为UserSetting是“稀疏的”。

此外给出:实体应该通过JPA获取,Hibernate作为提供者。

假设ProjectUserSetting表可能非常大。优化数据库架构不应受此问题的影响。假设存在有效的索引。

对于给定的用户,我希望有效地获取所有项目,包括该特定用户的收藏状态。请注意排序标准!

我最初的方法是制定以下JPQL查询:

SELECT p, us FROM Project p
    LEFT JOIN FETCH UserSetting us
    WHERE us.username IS NULL OR us.username = :currentUser
    ORDER BY COALESCE(us.favorite, false) DESC, p.name ASC

如果currentUser UserSettinguserBUserSetting,则此功能无效。 userB的{​​{1}}将被加入,但由于WHERE条款,项目不会列出。

幸运的是,JPA 2.1 introduces JOINS with ON clauseJavadoc)可用于将查询重新表述为:

SELECT p, us FROM Project p
    LEFT JOIN FETCH UserSetting us
    ON us.username IS NULL OR us.username = :currentUser
    ORDER BY COALESCE(us.favorite, false) DESC, p.name ASC

不幸的是,Hibernate(4.3.6)不支持使用“ ON子句”(Hibernate的语言中的“ WITH clause ”)进行提取连接,并退出以下异常:

org.hibernate.hql.internal.ast.QuerySyntaxException: with-clause not allowed on fetched associations; use filters

如何重新构造查询以实现功能并实现我的约束:

  • 固定域名模型
  • 可以很好地扩展的高效查询
  • JPA + Hibernate
  • 应避免使用Hibernate特定功能

2 个答案:

答案 0 :(得分:5)

您可以使用以下方法检索没有UserSettings的Project:

SELECT p, us FROM Project p
LEFT JOIN FETCH UserSetting us
WHERE us is null OR us.username IS NULL OR us.username = :currentUser
ORDER BY COALESCE(us.favorite, false) DESC, p.name ASC

 us is null
查询的WHERE子句中的

部分可以解决问题。

答案 1 :(得分:1)

最近的发现是JPA 2.1 (JSR 338)规范定义了语法而没有允许" ON子句"用于获取连接。

我的解决方法是省略Hibernate的对象映射功能,并明确选择ProjectUserSetting所需的字段。