jpa - JPQL 查询:属于多个类别的项目
问题描述
有一个实体Items有一个名为categories的集合字段,我需要找到至少属于两个特定类别的项目,但我找不到构建正确 JPQL 查询的方法。
@Entity
public class Items {
@ManyToMany (fetch = FetchType.EAGER)
private List<Category> categories;
}
我可以找到具有一个类别的项目:
SELECT i FROM Item i WHERE :cat MEMBER OF item.categories
我可以选择几个类别中的任何一个:
SELECT i FROM Item i WHERE :cat1 MEMBER OF item.categories OR :cat MEMBER OF item.categories
但是,当我尝试选择至少具有两个特定类别的项目时,以下查询不会获得任何项目:
SELECT i FROM Item i WHERE :cat1 MEMBER OF item.categories AND :cat2 MEMBER OF item.categories
哪种方法是正确的?
最好的问候,巴勃罗。
解决方案
这个问题发生在我的 ObjectDB 身上。我也联系过他们,答案是:
这似乎是 JPQL 查询在执行之前如何转换为类似 SQL 的语法的结果。MEMBER OF 是使用 JOIN 和一个新的合成变量来实现的,用于对集合进行迭代。在您的查询中 item.categories 出现两次,但用于迭代该集合的相同合成变量用于两次出现,并且该变量不能将 AND 的两侧与相同的值匹配。
可能我们可能不得不对每个 MEMBER OF 使用单独的迭代,因为您的帖子所证明的结果似乎是不可接受的(尽管由于转换为 JOIN,JQPL 本身在某些已知情况下具有奇怪的行为)。但是,使用单独的变量有时可能会使查询更加复杂和不必要地变慢(例如,对于您帖子中的 OR 查询),因此任何更改都需要仔细规划。
作为一种快速的解决方案,您可以用 2 个显式 JOIN 变量替换 MEMBER OF 的 AND,以便使用 2 个自变量对集合进行迭代。
因此,解决方案是使用以下查询:
SELECT DISTINCT item
FROM Item item JOIN item.categories cat1 JOIN item.categories cat2
WHERE cat1 = :cat1 AND cat2 = :cat2
我不知道这是否仅适用于这个特定的 JPA 实现(ObjectDB)。无论如何,如果有人有类似的问题,我希望这篇文章可以提供帮助。
推荐阅读
- selenium - ChromeDriver 版本适用于 Chrome 版本 69.0.3497.81,同时将 selenium 与 Python 一起使用
- html - 以及遵循 svg 多边形轮廓的 svg 路径
- php - 如何让我的系统更安全?我可以看到一些入侵者试图破解我的 Web 应用程序
- javascript - JavaScript 对象获取子对象中属性的值
- python-3.x - 使用 python notebook 进行网页抓取
- spring-boot - Springboot身份验证问题
- html - 如果我添加此代码, ::after 缩放将从更高的一些像素开始
- python - 重命名文件夹中的文件,通过更改文件名前面的前缀,取决于文件夹中的文件数量
- sql - 在另一个查询中使用一个查询的结果
- apache - 如何通过 Apache 服务器将 Kerberos 票证传递给后端服务