java - JPA Criteria API - 在 ElementCollection 外键上使用 WHERE 条件加入 ElementCollection
问题描述
我有一个实体 Document 和 enum Label (不是我的真实案例,我正在使用类比)。文档可以有一组标签。标签的映射如下:
@Entity
public class Document {
...
@ElementCollection(fetch = FetchType.EAGER)
@Enumerated(EnumType.STRING)
@Column(name = "labels")
private Set<Label> labels = new HashSet<>();
...
}
这意味着标签被映射到具有两列(document_id,value)的单独表中,但在 Java 中它只是枚举
我需要选择没有任何列出标签的文档。在 SQL 中,它看起来像这样:
select D.id
from document D left join label L
on D.id = L.document_id and L.value in('label1','label2',...)
where L.document_id is null
但我不知道如何在 JPA Criteria API 中编写它。我不知道如何在标签表中表达外键。JPA 谓词应该是这样的
CriteriaBuilder cd = ...
SetJoin<Object, Object> labelsJoin = root.joinSet("labels", JoinType.LEFT);
cb.and(labelsJoin .in("label1","label2"), cb.isNull(...???...)));
提前感谢您的建议。卢卡斯
解决方案
这应该返回预期的结果,但查询语句有点不同
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Document> query = cb.createQuery(Document.class);
Root<Document> root = query.from(Document.class);
Subquery<Long> subquery = query.subquery(Long.class);
Root<Document> subRoot = subquery.from(Document.class);
Join<Document, Label> label = subRoot.join("labels", JoinType.INNER);
List<Label> labels = Arrays.asList(Label.LABEL_1, Label.LABEL_2);
subquery.select(subRoot.get("id")).where(
cb.equal(root.get("id"), subRoot.get("id")),
label.in(labels)
);
query.select(root).where(cb.exists(subquery).not());
List<Document> result = entityManager.creteQuery(query).getResultList();
推荐阅读
- flutter - 颤振:无法从pdf文件打开特定页面
- c++ - MinGW 32/64 不能编译为 32 位
- bert-language-model - BERT 和 GPT2 之间的主要区别?
- node.js - 如何在节点 js 中更改 api url 的参数?
- react-native - React Native Image Rotation 滞后问题。如何解决?
- spring - 同一个 Spring Batch 步骤中的多个 ItemProcessor 和 ItemWriters
- typescript - 带有联合参数的打字稿抽象类方法
- python - 执行删除节点时 Dijkstra 算法出错
- javascript - 延迟加载图像 - 每秒最大 x
- ios - 如何在 Flutter 中阻止 IOS 上的屏幕截图