JPA:多个值匹配多个值

时间:2013-09-08 14:19:24

标签: java jpa

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

对于以下示例,提供了标记,查询将返回所有匹配所有标记的文档。如何在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;
}

2 个答案:

答案 0 :(得分: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。

答案 1 :(得分: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