The simplest approach I can think of is to do two count queries:
- A count of the number of keywords IN the set
- A count of the number of keywords NOT IN the set
The result of #1 should equal the number of keywords in the set. The result of #2 should equal 0. For example:
List<Request> requests =
em.createQuery("select r from Request r " +
"where (select count(k1) from Request r1 " +
" join r1.keywords k1 " +
" where r1 = r and k1 in :keywords) = :numKeywords " +
"and (select count(k2) from Request r2 " +
" join r2.keywords k2 " +
" where r2 = r and k2 not in :keywords) = 0", Request.class)
.setParameter("keywords", keywords)
.setParameter("numKeywords", keywords.size())
.getResultList();
If all you cared about was whether or not the set is a subset of the Request's keywords, then the second count is not needed. This can be done in a single query with a group by:
List<Request> requests =
em.createQuery("select r from Request r " +
"join r.keywords k " +
"where k in :keywords " +
"group by r " +
"having count(r) = :numKeywords", Request.class)
.setParameter("keywords", keywords)
.setParameter("numKeywords", keywords.size())
.getResultList();