title: Spring repository filter by using an object
body: <p>So I'm making use of <code>PaginAndSortingRepository&lt;&gt;</code> in Spring. Now I have an object that is bound to this repository. Let's call it <code>AuditLogEntry</code>. So my becomes <code>PagingAndSortingRepository&lt;AuditLogEntry, Long&gt;</code>. I need to apply some filters to this repository, so I created a new model called <code>AuditLogEntryFilter</code>. This is not bound to the AuditLogEntry itself, but I want to use this object to filter out my <code>AuditLogEntry</code>'s. The first approach that I've came up with myself is make methods for each of the filter's properties that can be different. This becomes very complicated when the filter' size is expanding. The thing I want to do is this:</p>
  
  <pre><code>List&lt;AuditLogEntry&gt; filterByAuditLogEntryFilter(AuditLogEntryFilter filter);
  </code></pre>
  
  <p>Does anybody has an idea how to accomplish this? I already looked into make an implementation of the PagingAndSortingRepository, but then I have to implement all of the other methods. Which I don't want to do.</p>
  
  <p><strong>Update solution:</strong></p>
  
  <p>Thanks to @Nikolay Rusev, I come up with the following solution: </p>
  
  <ol>
  <li><p>In my controller, I call my repository like this:</p>
  
  <pre><code>@RequestMapping(value = "/auditentries", method = RequestMethod.POST)
  public String processFilter(final AuditLogEntryFilter filter, BindingResult bindingResult, ModelMap
          modelMap, Pageable pageable) {
  
  Page&lt;AuditLogEntry&gt; auditLogEntryPage = auditLogEntryRepository.findAll(auditLogEntryFilterSpec(filter), pageable);
  
  modelMap.addAttribute("filter", filter);
  
  return "audit";
  
  }
  </code></pre></li>
  <li><p>Then I made a spec with roughly the following code:</p>
  
  <pre><code>public static Specification&lt;AuditLogEntry&gt; auditLogEntryFilterSpec(AuditLogEntryFilter filter) {
      return new Specification&lt;AuditLogEntry&gt;() {
  
  
          @Override
          public Predicate toPredicate(Root&lt;AuditLogEntry&gt; root, CriteriaQuery&lt;?&gt; criteriaQuery, CriteriaBuilder criteriaBuilder) {
  
              List&lt;Predicate&gt; predicateList = new ArrayList&lt;Predicate&gt;();
  
  
              if(filter.getDateFrom() != null || filter.getDateTo() != null) {
  
                  if(filter.getDateFrom() != null &amp;&amp; filter.getDateTo() == null)
                  {
                      Predicate auditLogEntryFromDatePredicate = criteriaBuilder.greaterThan(root.get("timestamp"), filter.getDateFrom());
                      predicateList.add(auditLogEntryFromDatePredicate);
                  }
  
                  if(filter.getDateFrom() == null &amp;&amp; filter.getDateTo() != null) {
                      Predicate auditLogEntryToDatePredicate = criteriaBuilder.lessThan(root.get("timestamp"), filter.getDateTo());
                      predicateList.add(auditLogEntryToDatePredicate);
                  }
  
                  if(filter.getDateFrom() != null &amp;&amp; filter.getDateTo() != null) {
                      Predicate auditLogEntryFromDatePredicate = criteriaBuilder.greaterThan(root.get("timestamp"), filter.getDateFrom());
                      Predicate auditLogEntryToDatePredicate = criteriaBuilder.lessThan(root.get("timestamp"), filter.getDateTo());
                      predicateList.add(auditLogEntryFromDatePredicate);
                      predicateList.add(auditLogEntryToDatePredicate);
                  }
  
              }
  
              Predicate[] predicates = new Predicate[predicateList.size()];
              predicateList.toArray(predicates);
  
              return criteriaBuilder.and(predicates);
          }
      };
  }
  </code></pre></li>
  </ol>
  
  <p>Now it retrieves the right results according to the filters.</p>