我目前Map<String, String>在 API 請求正文中收到一個。我有一個物體,
class TagEntity {
@Column(name = "name", length = 128, nullable = false)
private String name;
@Column(name = "value", length = 256, nullable = false)
private String value;
}
有一個MachineEntity有一個Set<TagEntity>。這是一個@OneToMany映射。我正在嘗試根據 獲取機器物體name并value傳入HashMap(請求中)對應于TagEntity.
我在下面嘗試了這段代碼。但是,它僅在我在請求中傳遞一個名稱-值對時才有效。假設,如果HashMap包含 2 個元素,則查詢在應該回傳 2 個機器物體時回傳一個空串列。
SetJoin<MachineEntity, TagEntity> join = root.join(MachineEntity_.tagEntities);
for (Map.Entry element : request.getTags().entrySet()) {
predicates.add(criteriaBuilder.and(
criteriaBuilder.equal(join.get(TagEntity_.name), element.getKey()),
criteriaBuilder.equal(join.get(TagEntity_.value), element.getValue())
));
}
有沒有一種方法可以HashMap在CriteriaBuilder不迭代的情況下設定Map?我不知道可以做些什么來解決這個問題。將不勝感激一些幫助。
uj5u.com熱心網友回復:
與往常一樣,用(大致)SQL 撰寫陳述句有助于:
SELECT ...
FROM Machine m
WHERE -- repeat for each map entry
EXISTS (SELECT ... FROM Tag t WHERE t.machine_id = m.id AND t.name = ?1 AND t.value = ?2)
AND EXISTS (SELECT ... FROM Tag t WHERE t.machine_id = m.id AND t.name = ?3 AND t.value = ?4)
...
如果這符合您的需要,可以將其大致轉換為標準 API,如下所示(您可能需要對其進行調整):
private Subquery<TagEntity> makeExistsSubquery(CriteriaQuery<MachineEntity> q, CriteriaBuilder cb, Map.Entry<String,String> e) {
Subquery<TagEntity> subquery = q.subquery(TagEntity.class);
Root<TagEntity> tagRoot = subquery.from(TagEntity.class);
subquery.where(cb.and(
cb.equal(tagRoot.get(TagEntity_.name), e.getKey()),
cb.equal(tagRoot.get(TagEntity_.value), e.getValue())
));
return subquery;
}
private void your_method() {
// assuming something like this exists:
CriteriaQuery<MachineEntity> query = criteriaBuilder.createQuery(MachineEntity.class);
// do this:
for (Map.Entry element : request.getTags().entrySet()) {
predicates.add(criteriaBuilder.exists(makeExistsSubquery(query, criteriaBuilder, element)));
}
...
}
我不確定此查詢的效率如何。但我希望這暗示了一個解決方案。
此外,我假設您想要匹配所有給定標簽的機器。如果您希望機器匹配任何給定標簽,SQL 查詢會更簡單:
SELECT ...
FROM Machine m JOIN Tag t ON t.machine_id = m.id
WHERE -- repeat for each map entry
t.name = ?1 AND t.value = ?2
OR t.name = ?3 AND t.value = ?4
...
Predicate tagsPredicate = criteriaBuilder.or(
request.getTags().entrySet().stream()
.map(e -> criteriaBuilder.and(
criteriaBuilder.equal(join.get(TagEntity_.name), e.getKey()),
criteriaBuilder.equal(join.get(TagEntity_.value), e.getValue())
))
.collect(Collectors.toList())
.toArray(new Predicate[0])
);
// add the tagsPredicate to your where clause, if the user has actually defined tag criteria
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/416060.html
標籤:
