2

I have the following entities:

@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
}

How can I efficiently find all Article entities that have a common set of tags?

The naive approach is to find all the articles that belong to each tag and then return the intersection of all the article sets. Something like:

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;
}

My question is "Is there more efficient way of doing this, that does not require to fetch possibly all the articles from the DB, like this one ? Maybe through a JPQL query or using the CriteriaBuilder (I've never used it before)"

4

1 回答 1

6
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)

这基本上计算了文章的标签是接受的标签集中的标签,并且这些标签的数量是否等于接受的标签集的大小(意味着集合中的所有标签都是文章的标签) ,返回文章。

于 2014-02-08T11:40:01.513 回答