4

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?

kiedysktos
  • 3,910
  • 7
  • 31
  • 40
James Pace
  • 637
  • 8
  • 14
  • You highlight a real problem that I've also seen in spring-data-jpa. We have one search that could potentially user over 10 different query parameters and filter fields...as you can imagine spring-data-jpa breaks down super quick. – teuber789 Apr 14 '17 at 18:42

1 Answers1

2

The easiest option is Query By Example: http://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#query-by-example

When to use

  • Querying your data store with a set of static or dynamic constraints
  • Frequent refactoring of the domain objects without worrying about breaking existing queries
  • Works independently from the underlying data store API

Limitations

  • No support for nested/grouped property constraints like firstname = ?0 or (firstname = ?1 and lastname = ?2)
  • Only supports starts/contains/ends/regex matching for strings and exact matching for other property types

Take a look also at this question: Dynamic spring data jpa repository query with arbitrary AND clauses

Community
  • 1
  • 1
Robert Niestroj
  • 15,299
  • 14
  • 76
  • 119