代码之家  ›  专栏  ›  技术社区  ›  Franz Wong

JPA:多个值匹配多个值

  •  0
  • Franz Wong  · 技术社区  · 13 年前

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

    对于以下示例,提供了标记,查询将返回所有标记匹配的所有文档。如何在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 回复  |  直到 13 年前
        1
  •  0
  •   paulek    13 年前

    我不知道完美的解决方案,但这会奏效:

    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。

        2
  •  0
  •   Franz Wong    12 年前

    @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