Results 1 to 4 of 4

Thread: Why can't a Spring Data Specification return a null Predicate?

  1. #1
    Join Date
    May 2005
    Location
    BEEK, The Netherlands
    Posts
    230

    Default Why can't a Spring Data Specification return a null Predicate?

    Why can't a Spring Data Specification return a null Predicate? Would't it be sensible to not add it to criteria query if Specification.toPredicate returns null?

    I have the following use case:

    String q = "<some search query>" // this can be something like "Davy Jones" or "31-12-2011"
    Page<Receipt> page = receiptRepository.findAll(where(receiptDateEquals( q)).or(customerNameContains(q)), pageable);

    Think about q as a generic query string submitted via a web search form.
    Then in the receiptDateEquals specification I'm converting the search query to a date, if it succeeds fine and return the appropriate predicate, otherwise return no predicate / null.

    It's off course debatable if I should the date conversion in the specification or in the controller itself.
    I would like to opt for a central place in the specification itself so calling controller actions don't have to take care.

    That's why I wonder why the Sepcifciation.toPredicate can'y just return null if needed.

  2. #2
    Join Date
    May 2005
    Location
    BEEK, The Netherlands
    Posts
    230

    Default

    I'm now just returning a Predicate which basically checks if date = null which also works.
    But I don't know if this works in all databases as it might return the receipts which have an actual null date (= null vs is null).
    That's why I think it would be better to return null from toPredicate method.


    public static Specification<Receipt> receiptDateEquals(final Date date) {
    return new Specification<Receipt>() {
    @Override
    public Predicate toPredicate(Root<Receipt> receipt, CriteriaQuery<?> query, CriteriaBuilder builder) {
    return builder.equal(receipt.<Date> get("receiptDate"), date);
    }
    };
    }

    public static Specification<Receipt> receiptDateEquals(final String str) {
    return new Specification<Receipt>() {
    @Override
    public Predicate toPredicate(Root<Receipt> receipt, CriteriaQuery<?> query, CriteriaBuilder builder) {
    Date date = null;
    try {
    date = DateUtils.parseDateStrictly(str, "dd-MM-yyyy");
    } catch (Exception e) {
    // ignore
    }
    return receiptDateEquals(date).toPredicate(receipt, query, builder);
    }
    };
    }

  3. #3
    Join Date
    Apr 2006
    Location
    Dresden, Germany
    Posts
    483

    Default

    Generally, they can as SimpleJpaRepository only applies the where clause if the predicate handed into the method is not null. This is just to be safe if people violate the contract defined in Specification. Does it really make sense to delay the Date parsing that much? Passing data around as Strings is not a good idea in general so why not parse the date upfront and only apply the entire specification if it's a valid date. Otherwise you essentially write

    Code:
    ….findAll(where(receiptDateEquals(yourString)));
    and would get *all* data back in case the given String is incorrect. This is not only problematic from a debugging perspective, I'd argue it's just not what you defined you want to get back, because if the date is invalid there are essentially *no* results with that "date". This leads to the more abstract questions how to deal with null specifications and the predicates generated in turn. I don't think that transparently dropping them is an appropriate approach as your sample above shows.

    PS: You might wanna use [ code ] tags when posting larger snippets of code as otherwise the stuff is very hard to read.

  4. #4
    Join Date
    May 2005
    Location
    BEEK, The Netherlands
    Posts
    230

    Default

    Hi Oliver,

    I understand the 'contract' point, and it's fair point.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •