title: Correct usage of JPA criteria API, Predicates and where method of CriteriaQuery
body: <p>I am trying to test a JPA repository. Here is my client/test code:</p>
  
  <pre><code>@Test
      public void testFindBoitesByMultiFieldWithIdentifiantSet() {
          BoiteDataOnDemand dod = new BoiteDataOnDemand();
          Boite boite = dod.getSpecificBoite(0);
          boite.setIdentifiant("theIdentifiant");
          boiteRepository.save(boite);
          assertEquals(10, Boite.countBoites());
          BoiteQueryInfo boiteQueryInfo = new BoiteQueryInfo();
          boiteQueryInfo.setIdentifiant("theIdentifiant");
          List&lt;Boite&gt; boites = boiteRepository.findBoitesByMultiField(boiteQueryInfo, 1, 5, "identifiant", "desc");
          assertEquals(1, boites.size());
      }
  </code></pre>
  
  <p>Here is the repository method:</p>
  
  <pre><code>@Override
      public List&lt;Boite&gt; findBoitesByMultiField(BoiteQueryInfo boiteQueryInfo, Integer firstResult_, Integer maxResults_, String sort_, String order_) {
          log.debug("findBoitesByMultiField");
  
          final String identifiant = boiteQueryInfo.getIdentifiant();
          final Date dateOuvertureFrom = boiteQueryInfo.getDateOuvertureFrom();
  
          CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
          CriteriaQuery&lt;Boite&gt; c = criteriaBuilder.createQuery(Boite.class);
          Root&lt;Boite&gt; boite = c.from(Boite.class);
          List&lt;Predicate&gt; criteria = new ArrayList&lt;Predicate&gt;();
              ...
          if (identifiant != null &amp;&amp; !identifiant.trim().equals("")) {
              ParameterExpression&lt;String&gt; parameter = criteriaBuilder.parameter(String.class, "identifiant");
              Predicate condition = criteriaBuilder.like(boite.&lt;String&gt; get("identifiant"), parameter);
              criteria.add(condition);
          }
  
          if (dateOuvertureFrom != null &amp;&amp; dateOuvertureTo != null) {
              ParameterExpression&lt;Date&gt; parameterDateOuvertureFrom = criteriaBuilder.parameter(Date.class, "dateOuvertureFrom");
              ParameterExpression&lt;Date&gt; parameterDateOuvertureTo = criteriaBuilder.parameter(Date.class, "dateOuvertureTo");
              Predicate condition = criteriaBuilder.between(boite.&lt;Date&gt; get("dateOuverture"), parameterDateOuvertureFrom, parameterDateOuvertureTo);
              criteria.add(condition);
          } else if (dateOuvertureFrom != null) {
              ParameterExpression&lt;Date&gt; parameter = criteriaBuilder.parameter(Date.class, "dateOuvertureFrom");
              Predicate condition = criteriaBuilder.greaterThanOrEqualTo(boite.&lt;Date&gt; get("dateOuverture"), parameter);
              criteria.add(condition);
          } else if (dateOuvertureTo != null) {
              ParameterExpression&lt;Date&gt; parameter = criteriaBuilder.parameter(Date.class, "dateOuvertureTo");
              Predicate condition = criteriaBuilder.lessThanOrEqualTo(boite.&lt;Date&gt; get("dateOuverture"), parameter);
              criteria.add(condition);
          }
  
              ...    
          if (order.equalsIgnoreCase("desc")) {
              c.orderBy(criteriaBuilder.desc(boite.get(sort)));
          } else {
              c.orderBy(criteriaBuilder.asc(boite.get(sort)));
          }
  
          for (Predicate predicate : criteria) {
              c.where(criteriaBuilder.and(predicate));
          }
  
          TypedQuery&lt;Boite&gt; q = em.createQuery(c);
  
          if (identifiant != null &amp;&amp; !identifiant.trim().equals("")) {
              q.setParameter("identifiant", "%" + identifiant + "%");
          }
  
          if (dateOuvertureFrom != null &amp;&amp; dateOuvertureTo != null) {
              q.setParameter("dateOuvertureFrom", dateOuvertureFrom);
              q.setParameter("dateOuvertureTo", dateOuvertureTo);
          } else if (dateOuvertureFrom != null) {
              q.setParameter("dateOuvertureFrom", dateOuvertureFrom);
          } else if (dateOuvertureTo != null) {
              q.setParameter("dateOuvertureTo", dateOuvertureTo);
          }
  
              ...    
          return q.setFirstResult(firstResult).setMaxResults(maxResults).getResultList();
      }
  </code></pre>
  
  <p>However, the test always fails at <strong><code>assertEquals(1, boites.size());</code></strong> indicating that no result is returned i.e. (<code>java.lang.AssertionError: expected:&lt;1&gt; but was:&lt;0&gt;</code>).</p>
  
  <p>I strongly suspect something is wrong here:</p>
  
  <pre><code>for (Predicate predicate : criteria) {
              c.where(criteriaBuilder.and(predicate));
          }
  </code></pre>
  
  <p>But I am not sure how to "and" the criteria.</p>
  
  <p>Can anyone please provide advice?</p>
  
  <p>P.S. FYI, <code>BoiteDataOnDemand</code> inserts random 10 rows into the <code>boite</code> table.</p>
  
  <p>EDIT: code was edited to make it shorter.</p>