0

如何通过多个值匹配多个值?(所有匹配)

对于以下示例,提供了标签,查询将返回所有标签匹配的所有文档。如何在 JPA 中做到这一点?谢谢。

数据:

Document 1 : { id: 1, name: "doc1", tags: [1, 2] }
Document 2 : { id: 2, name: "doc2", tags: [2, 3] }
Tag 1 : { id: 1, name: "tag1" }
Tag 2 : { id: 2, name: "tag2" }
Tag 3 : { id: 3, name: "tag3" }

场景:

Criteria: "tag1", "tag2"
=> Return: "doc1"

Criteria: "tag1", "tag2", "tag3"
=> Return: Nothing

Criteria: "tag2"
=> Return: "doc1" and "doc2"

实体:

public class Document {
    @Id
    private Long id;

    @Column
    private String name;

    @ManyToMany
    @JoinTable(name = "DOCUMENT_TAG_RLAT")
    private List<Tag> tags;
}

public class Tag {
    @Id
    private Long id;

    @Column
    private String name;
}
4

2 回答 2

0

我不知道完美的解决方案,但这会起作用:

public List<Document> documentsByTags(List<String> tagNames) {
    CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
    CriteriaQuery<Document> criteriaQuery = criteriaBuilder.createQuery(Document.class);
    Root<Document> documents = criteriaQuery.from(Document.class);
    List<Predicate> predicates = new ArrayList<Predicate>();

    for (String tagName : tagNames) {
        Subquery<Long> sq = criteriaQuery.subquery(Long.class);
        Root<Tag> tags = sq.from(Tag.class);
        sq.select(tags.<Long>get("documents")).where(
            criteriaBuilder.equal(tags.get("name"), tagName);
        predicates.add(criteriaBuilder.in(documents.<Long> get("id")).value(sq));
    }
    criteriaQuery.where(predicates.toArray(new Predicate[predicates.size()]));

    TypedQuery<Document> query = entityManager.createQuery(criteriaQuery);

    return query.getResultList();
}

另外,在我看来,您需要双向关系@ManyToMany(在您的文档属性上看不到您Tag.class可能只是没有粘贴),并且在您的@JoinTable注释中您必须指定 joinColumns 和 inverseJoinColumns。

于 2013-09-08T19:40:07.713 回答
0

@paulek 我没有尝试您的解决方案,但我想到了一个可行的解决方案。

select d from Document d 
where 
    (select count(t) from d.tags as t, Tag t2 where t.id = t2.id and t2 in (:tags)) 
    =
    :tagCount
于 2013-09-09T12:06:20.897 回答