I feel I've lived your same situation: my HTML form has N filters but I want they only apply to the search if they are selected or changed. Once you model your form binded with it's respective selects, inputs, etc... from the View, if any of these fields aren't selected or have the default value, just want to ignore but still using the convenience and ease of the Spring Repository
(in my case JpaRespository).
With my little Spring perspective I've tried to use the Specification approach (IMO better than implement your custom Repository). It works perfectly, but don't know if it's the best way.
Here is an official Spring example https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/
And here a personal example a little simplified (and probably breaking some best coding practices, with the aim to be understandable):
MyObjectRepository.java
public interface MyObjectRepository extends JpaRepository<MyObject, Long>, JpaSpecificationExecutor<MyObject> { }
MyObjectServiceImpl.java
@Service("MyObjectService")
public class MyObjectServiceImpl implements MyObjectService {
@Autowired
MyObjectRepository myObjectRespository;
@Override
public Page<MyObject> getAllMyObjectByFields(int pageIndex, FormMyObject formMyObject) {
Specification<MyObject> spec = new Specification<MyObject>() {
@Override
public Predicate toPredicate(Root<MyObject> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
if (formMyObject == null) {
throw new IllegalStateException("At least one parameter should be provided to construct complex query");
}
List<Predicate> predicates = new ArrayList<Predicate>();
// only if the content is present add a criteria to the search, you decide/know if will be null, or empty...
if (formMyObject.getYourField() != null && formMyObject.getYourField().length() > 0) {
predicates.add(
builder.and(builder.equal(root.get("field"), formMyObject.getYourField())));
}
// add as many criteria as you want/need
if(){
predicates.add( ... );
}
Predicate[] predicatesArray = new Predicate[predicates.size()];
return builder.and(predicates.toArray(predicatesArray));
}
};
PageRequest page = new PageRequest(pageIndex, formMyObject.getMaxResult());
// using the built in findAll method from Repository with dynamic custom filters
return myObjectRespository.findAll(spec, page);