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

HQL checking if object contains all element s of requested set - duplicate

我有两个实体。例如,帖子和标签。 我必须编写一个方法,该方法将只接受查询中提到的具有所有标签的帖子。

我试过了

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

但是,如果至少有一个标签包含在 tagSet 中,则需要 Post。

如何仅使用 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;
}

TAGS table 应该有主键。

我们可以将主键的一组标签对象传递给 NamedParameter 查询,然后您只会得到映射到标签对象的 Post 个对象。

您必须针对多对多对象编写查询。

示例: 查询 = SELECT mm.post 来自 POST_TAG_MM mm WHERE mm.tag.primarykeycolumn 在 (:postPrimaryKeySet);

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

如有任何问题请告诉我

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

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 直接创建它并手动设置所需的参数,这样您就不会强制客户端了解查询语义细节的方法。