HQL检查对象是否包含所请求集的所有元素 - 重复

时间:2016-02-13 11:13:21

标签: java spring hibernate jpa hql

我有两个实体。例如,帖子和标签。 我必须编写一个方法,该方法仅包含查询中提到的所有标记的帖子。

我试过

@Query("select distinct p from posts p join p.tags t where t in ?1")
Page<Post> findDistinctByTagsIn(Set<Tag> tagSet, Pageable pageable);

然而,如果tagSet中包含至少一个标签,则需要发布。

如何仅使用HQL和JPA存储库解决此问题?

@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(name = "posts_tags", joinColumns = {
        @JoinColumn(name = "post_id", nullable = false, updatable = false)},
        inverseJoinColumns = {@JoinColumn(name = "tag_id")})
public Set<Tag> getTags() {
    return tags;
}

2 个答案:

答案 0 :(得分:1)

您必须按帖子分组,只选择匹配记录数等于传入标记数的帖子(意味着所有标记都匹配):

select p from Posts p join p.tags t
where t in :tags
group by p
having count(p) = :tagsSize

但是,您必须传递额外的tagsSize参数,其值为tagSet.size()

您可以更改存储库方法签名以接受此参数,并调用以下方法:

repo.findDistinctByTagsIn(tagSet, tagSet.size(), Pageable pageable);

并且,为了避免冗余,稍后将其更改为在Spring adds support for it

时使用SpEL表达式
@Query("select p from Posts p join p.tags t where t in :tags "
     + "group by p having count(p) = :#{#tags.size()}")
Page<Post> findDistinctByTagsIn(@Param("tags") Set<Tag> tagSet, Pageable pageable);

或者,随着查询变得有点复杂,您可以使用EntityManager在单独的方法中直接创建它并手动设置所需的参数,这样就不会强制客户端方法要知道查询语义的细节。

答案 1 :(得分:-1)

TAGS表应该有主键。

我们可以将主键的标签对象集传递给NamedParameter查询,然后只获得映射到Tag对象的Post对象。

你必须针对很多对象编写查询。

示例: query = SELECT mm.post FROM POST_TAG_MM mm WHERE mm.tag.primarykeycolumn in(:postPrimaryKeySet);

查询q = s.getNamedQuery(查询);     q.setParameterList(“postPrimaryKeySet”,tagsPrimyKeySet);

如果您有任何疑问,请与我们联系