我有以下实体:
@Entity
public class Article{
@Id
private String id;
@ManyToMany(cascade = CascadeType.PERSIST)
private Set<Tag> tags;
//non-relevant code
}
@Entity
public class Tag{
@Id
private String id;
@Basic
@Column(nullable = false, unique = true, length = 32)
private String name;
//non-relevant code
}
如何有效地找到具有共同标记set
的所有Article
实体?
天真的方法是查找属于每个tag
的所有文章,然后返回所有文章集的intersection
。像这样:
public Set<Article> findByTags(Set<Tag> tags){
Set<Article> result = new HashSet<>();
if(tags.isEmpty()){
return result;
}
Iterator<Tag> i = tags.iterator();
result.addAll(i.next().getArticles());
while(i.hasNext() && !result.isEmpty()){
result.retainAll(i.next());
}
return result;
}
我的问题是"有没有更有效的方法可以做到这一点,不需要从数据库中获取所有文章,就像这个一样?也许通过 JPQL 查询或使用CriteriaBuilder
(我以前从未使用过)"
select a from Article a where :numberOfTags =
(select count(distinct tag.id) from Article a2
inner join a2.tags tag
where tag in :tags
and a = a2)
这基本上计算在接受的标签集中作为标签的文章的标签,如果此类标签的数量与接受的标签集的大小(意味着集合中的所有标签都是文章的标签)相等,则返回文章。