7

我有一个包含 M:N 元素(标签)集合的对象(BlogPost)。

如何使用 JPA2(Hibernate)查询一个对象(BlogPost),其中至少一个它的标签与一组标签(由用户定义)中的一个元素匹配。

findBlogPostWithAtLeastOneMatchingTag(Collection<Tag> tags){ ???? }

我的主要问题是,我实际上需要比较两个标签集合: - BlogPost 的标签集合。- 我搜索的收藏

我试过Select p from Post p where p.tags in(:tags)但它不起作用,因为我的帖子实体不止一个标签。

那么我能做些什么呢?

我的 BlogPost 实体看起来像这样。它有几个标签。

@Entity
public class BlogPost{

    /** The tags. */
    @ManyToMany()
    @NotNull
    private Set<Tag> tags;

    @NotBlank
    private String content;

    ...
}

解决方案不能是 JPQL,JPA-Criteria(不是 Hibernate-Criteria)也可以。

4

3 回答 3

8

如果您喜欢 JPA Criteria,这是适合您的解决方案:

List<Integer> myTagsIds = new ArrayList<Integer> ();
myTagsIds.add(1);
myTagsIds.add(2);

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<BlogPost> cq = cb.createQuery(BlogPost.class);
Root<BlogPost> blogPost = cq.from(BlogPost.class);
SetJoin<BlogPost, Tag> tags = blogPost.join(BlogPost_.tags);
Predicate predicate = tags.get(Tag_.id).in(myTagsIds);
cq.distinct(true);
cq.where(predicate);
TypedQuery<BlogPost> tq = em.createQuery(cq);
return tq.getResultList();

此解决方案使用规范的 MetaModelBlogPost_Tag_并且应该由您的 JPA 实现生成。

于 2012-07-05T16:59:34.623 回答
2

方法一:

在 SQL 中,它可能类似于:

SELECT p FROM Post p WHERE (p.tags INTERSECT :tags IS NOT EMPTY);

然后应用@SqlResultSetMapping.

方法二:

您可以Criteria API像以前一样使用和启动,但循环Collection<Tag> tags如下:

* make a union of single query results from `Select p from Post p where p.tags in(:tags)`;
* take distinct over result of union.

查询将是服务器端的,您不必在 Java 中做脏活。

于 2012-07-05T14:55:00.117 回答
1

你可以做类似的事情

Select t from Post t where t.tag in (select p.tag from Post p where p.id=:id)

id 是当前帖子的 id。基本上,您正在选择带有当前帖子标签中标签的帖子。

于 2012-07-02T16:14:06.930 回答