spring-data-mongodb has a really nice and simple query builder. I have multiple search parameters that I would like to search on, some or none may be provided. This is achieved very simply in spring-data-mongodb and it leverages the use of the Pageable and Page classes:
Query query = new Query().with(pageable);
if (searchParameters.getPublished() != null) {
query.addCriteria(Criteria.where("published").is(searchParameters.getPublished()));
}
List<Property> propertyList = mongoTemplate.find(query, Property.class);
long count = mongoTemplate.count(query, Property.class);
List<PropertySummary> propertySummaryList = propertyList.stream()
.map(propertyConverter::convert)
.collect(Collectors.toList());
return new PageImpl<>(propertySummaryList, pageable, count);
Does anything like this exist in spring-data-jpa? From spending a day looking around I would say no. There is the criteria api but that doesn't integrate with the pageable and page classes, which is very annoying. spring-data-jpa seems to be great at writing query methods for you where you want to search on a single field all the time. But the library falls apart very quickly when you wan't to do anything remotely harder than findCusomterByLastName(String lastName)
. If you specify multiple parameters then they all actually have to have something set for the search, if one of them is null then it will match fields that have the value null.
The specification api seems like a good idea, but you have to be able to define you query in a single fluent declaration. If you want to conditionally add specs together the api falls apart very quickly.
The QueryDslPredicateExecutor which allows integration with the QueryDSL library on the face seems useful. However it relies heavily on the annotation-post-processors to auto-generate code for you. This is great but only adds the ability to create type safe queries. You can then pass predicates to your repositories, but again this seems to fall apart quite quickly. How can you combine predicates together? The only way I have found is using them via Specifications.where().and()
which is not great (see previous paragraph).
Does anyone else share these frustrations? It seems like such a simple requirement. Is there something in spring-data-jpa that I've missed?