How to query an M:N relationship with JPA2?

criteria-api, hibernate, java, jpa-2.0, jpql

Solution

If you like JPA Criteria, this is the solution for you:

List<Integer> myTagsIds = new ArrayList<Integer> ();
myTagsIds.add(1);
myTagsIds.add(2);

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<BlogPost> cq = cb.createQuery(BlogPost.class);
Root<BlogPost> blogPost = cq.from(BlogPost.class);
SetJoin<BlogPost, Tag> tags = blogPost.join(BlogPost_.tags);
Predicate predicate = tags.get(Tag_.id).in(myTagsIds);
cq.distinct(true);
cq.where(predicate);
TypedQuery<BlogPost> tq = em.createQuery(cq);
return tq.getResultList();

This solution makes use of the canonical MetaModel classes `BlogPost_` and `Tag_` that should be generated by your JPA implementation.

Problem

I have an an object (BlogPost) that contains an M:N collection of elements (Tags). How to query for an object (BlogPost) where at least one it its Tags matches an element in a set of Tags (defined by the user) with JPA2 (Hibernate). ``` findBlogPostWithAtLeastOneMatchingTag(Collection<Tag> tags){ ???? } ``` My main problem is, that I actually need to compare two collections of tags: - the collection of tags of the BlogPost. - the collection I search for I tried `Select p from Post p where p.tags in(:tags)` but it does not work, as my post entities have more than just one tag. So what could I do instead? My BlogPost entity looks like this. It has several Tags. ``` @Entity public class BlogPost{ /** The tags. */ @ManyToMany() @NotNull private Set<Tag> tags; @NotBlank private String content; ... } ``` The solution must not be JPQL, JPA-Criteria (not Hibernate-Criteria) would be fine too.

Original source