我有两个实体。例如,帖子和标签。 我必须编写一个方法,该方法仅包含查询中提到的所有标记的帖子。
我试过
@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;
}
答案 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);
如果您有任何疑问,请与我们联系