title: JPA criteria to select entities with ElementCollection containing another collection
body: <p>There is an entity with <code>@ElementCollection</code> field:</p>
  <pre><code>@Data
  @Entity(name = &quot;Posts&quot;)
  public class PostEntity {
  
      @Id @GeneratedValue
      private Long id;
      private UserEntity author;
      @ElementCollection
      private Set&lt;String&gt; tags;
      // some more fields
  </code></pre>
  <p>I'm trying to implement a search by tags using criteria api and add it to the following method:</p>
  <pre><code>    public Page&lt;PostEntity&gt; getPosts(@NonNull UserEntity userEntity, Set&lt;String&gt; tags, LocalDateTime from, LocalDateTime to, @NonNull Pageable pageable) {
          CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
          CriteriaQuery&lt;PostEntity&gt; criteriaQuery = criteriaBuilder.createQuery(PostEntity.class);
          Root&lt;PostEntity&gt; post = criteriaQuery.from(PostEntity.class);
  
          List&lt;Predicate&gt; predicateList = new ArrayList&lt;&gt;();
          Predicate authorPredicate = criteriaBuilder.equal(post.get(&quot;author&quot;), userEntity);
          predicateList.add(authorPredicate);
  
          // !!!! Place for tagPredicate
          ...
  
          Predicate[] predicates = predicateList.toArray(Predicate[]::new);
          criteriaQuery.where(predicates);
  
          TypedQuery&lt;PostEntity&gt; query = entityManager.createQuery(criteriaQuery);
          query.setFirstResult(pageable.getPageNumber() * pageable.getPageSize());
          query.setMaxResults(pageable.getPageSize());
  
          List&lt;PostEntity&gt; resultList = query.getResultList();
  
  </code></pre>
  <p>There were two different attemts to achive the purpose, but none of them works as expected:</p>
  <p>First one</p>
  <pre><code>        if (tags != null) {
              for (String tag : tags) {
                  Predicate tagPredicate = criteriaBuilder.isMember(tag, post.get(&quot;tags&quot;));
                  predicateList.add(tagPredicate);
              }
          }
  </code></pre>
  <p>Second one</p>
  <pre><code>        if (tags != null) {
              Predicate tagsPredicate  = criteriaBuilder.conjunction();
              for (String tag : tags) {
                  Predicate tagPredicate = post.join(&quot;post_tags&quot;).in(tag);
                  criteriaBuilder.and(tagsPredicate, tagPredicate);
              }
              predicateList.add(tagsPredicate);
          }
  
  </code></pre>
  <p>The test represent desired behaviour:</p>
  <pre><code>    @Test
      @Transactional
      void gettingPostsByTagsTest() throws Exception {
          User user = integrationTestAdapter.createUser(&quot;test_user&quot;, &quot;any_email@ilon.fr&quot;, &quot;ol12Hi38&quot;);
          integrationTestAdapter.signUserUp(user);
          integrationTestAdapter.signUserIn(user);
          Post post = integrationTestAdapter.createPost(user, &quot;My first post&quot;, &quot;test text&quot;, Set.of());
          integrationTestAdapter.publishPost(post);
          Post post2 = integrationTestAdapter.createPost(user, &quot;My school day&quot;, &quot;test text&quot;, Set.of(&quot;school&quot;));
          integrationTestAdapter.publishPost(post2);
          Post post3 = integrationTestAdapter.createPost(user, &quot;Homework for tomorrow&quot;, &quot;test text&quot;, Set.of(&quot;school, homework&quot;));
          integrationTestAdapter.publishPost(post3);
          Post post4 = integrationTestAdapter.createPost(user, &quot;Homework for summer&quot;, &quot;test text&quot;, Set.of(&quot;school, homework, summer&quot;));
          integrationTestAdapter.publishPost(post4);
  
          Page&lt;Post&gt; postsWithoutTags = integrationTestAdapter.getPosts(user.getLogin(), null, null, null, null);
          assertEquals(4, postsWithoutTags.getContent().size());
  
          Page&lt;Post&gt; shcoolPosts = integrationTestAdapter.getPosts(user.getLogin(), Set.of(&quot;school&quot;), null, null, null);
          assertEquals(3, shcoolPosts.getContent().size());
  
          Page&lt;Post&gt; homeworkPosts = integrationTestAdapter.getPosts(user.getLogin(), Set.of(&quot;homework&quot;), null, null, null);
          assertEquals(2, homeworkPosts.getContent().size());
  
          Page&lt;Post&gt; schoolAndHomeworkPosts = integrationTestAdapter.getPosts(user.getLogin(), Set.of(&quot;school&quot;, &quot;homework&quot;), null, null, null);
          assertEquals(2, schoolAndHomeworkPosts.getContent().size());
  
          Page&lt;Post&gt; summerPosts = integrationTestAdapter.getPosts(user.getLogin(), Set.of(&quot;summer&quot;), null, null, null);
          assertEquals(1, summerPosts.getContent().size());
  
          Page&lt;Post&gt; summerAndHomeworkPosts = integrationTestAdapter.getPosts(user.getLogin(), Set.of(&quot;summer&quot;, &quot;homework&quot;), null, null, null);
          assertEquals(1, summerAndHomeworkPosts.getContent().size());
  
          Page&lt;Post&gt; summerAndSchoolPosts = integrationTestAdapter.getPosts(user.getLogin(), Set.of(&quot;school&quot;, &quot;summer&quot;), null, null, null);
          assertEquals(1, summerAndSchoolPosts.getContent().size());
  
          Page&lt;Post&gt; summerAndHomeworkAndSchoolPosts = integrationTestAdapter.getPosts(user.getLogin(), Set.of(&quot;school&quot;, &quot;homework&quot;, &quot;summer&quot;), null, null, null);
          assertEquals(1, summerAndHomeworkAndSchoolPosts.getContent().size());
  
          Page&lt;Post&gt; postsWithNonexistentTag = integrationTestAdapter.getPosts(user.getLogin(), Set.of(&quot;university&quot;), null, null, null);
          assertEquals(0, postsWithNonexistentTag.getContent().size());
      }
  </code></pre>