[英]Alternative to fetch join with “ON clause” in Hibernate
给定的是RDBMS中的以下域模型,它与Hibernate映射到Java对象中。
┌─────────┐ ┌─────────────┐
│ Project │ 1 0..n │ UserSetting │
├─────────┼------------┼─────────────┤
│ name │ │ username │
└─────────┘ │ favorite │
└─────────────┘
用户可以将项目标记为收藏,这由关联(可选) UserSetting
条目反映。 如果用户没有标记项目,则数据库中没有UserSetting
条目 ,这意味着项目不是最喜欢的。 认为UserSetting
是“稀疏的”。
另外给出:实体应该通过JPA以Hibernate作为提供者获取。
假设Project
和UserSetting
表可能非常大。 优化数据库架构不应受此问题的影响。 假设存在有效的索引。
对于给定的用户,我希望有效地获取所有项目,包括该特定用户的最爱状态。 注意排序标准!
我最初的方法是制定以下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
没有 UserSetting
但userB
了。 该UserSetting
的userB
将被加入,但该项目将不会列出由于WHERE
子句。
幸运的是, JPA 2.1引入了JOINS和ON子句 ( Javadoc ),可用于将查询重新表述为:
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子句 ”)进行提取连接,并退出时出现以下异常:
org.hibernate.hql.internal.ast.QuerySyntaxException: with-clause not allowed on fetched associations; use filters
如何重新构造查询以实现功能并满足我的约束:
您可以使用以下命令检索没有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子句中的部分功能。
最近的发现是JPA 2.1(JSR 338)规范定义了语法而没有允许用于获取连接的“ON子句”。
我的解决方法是省略Hibernate的对象映射功能,并明确选择Project
和UserSetting
所需的字段。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.