35

I have a method that does a search with filters, so I'm using Specification to build a dynamic query:

public Page<Foo> searchFoo(@NotNull Foo probe, @NotNull Pageable pageable) {

        Specification<Foo> spec = Specification.where(null);  // is this ok?

        if (probe.getName() != null) {
            spec.and(FooSpecs.containsName(probe.getName()));
        }
        if (probe.getState() != null) {
            spec.and(FooSpecs.hasState(probe.getState()));
        }
        //and so on...

        return fooRepo.findAll(spec, pageable);
}

There is the possibility that there are no filters specified, so I would list everything without filtering. So having that in mind, how I should initialize spec ? Right now, the code above doesn't work as it always returns me the same result: all the registers of the table, no filtering have been aplied althought and operations have been made.

FooSpecs:

public class PrescriptionSpecs {

    public static Specification<Prescription> containsCode(String code) {
        return (root, criteriaQuery, criteriaBuilder) ->
            criteriaBuilder.like(root.get(Prescription_.code), "%" + code + "%");
    }

    // some methods matching objects...
    public static Specification<Prescription> hasContractor(Contractor contractor) {
        return (root, criteriaQuery, criteriaBuilder) ->
            criteriaBuilder.equal(root.get(Prescription_.contractor), contractor);
    }
    //... also some methods that access nested objects, not sure about this
    public static Specification<Prescription> containsUserCode(String userCode) {
        return (root, criteriaQuery, criteriaBuilder) ->
            criteriaBuilder.like(root.get(Prescription_.user).get(User_.code), "%" + userCode + "%");
    }
}
7
  • What kind of exception do you get? I think this should work. Please add the stack trace. Also, why do you ask "is this ok?" if you already know "the code above doesn't work" Commented Jun 25, 2018 at 12:42
  • @JensSchauder There is no error but it doesn't filter. I'm getting all the results of the table, always. I ask if its is ok because I'm not sure if it is, I didn't see an example like this. Moreover, when I debug, i see spec empty. Commented Jun 25, 2018 at 12:49
  • I see. Can you share the code for FooSpecs? Commented Jun 25, 2018 at 13:13
  • updated with FooSpecs (aka PrescriptionSpecs) Commented Jun 25, 2018 at 13:24
  • Hmm, looks ok to me. Do they work on their own, like in fooRepo.findAll(containsUserCode("XXX"), pageable);? Commented Jun 25, 2018 at 13:35

2 Answers 2

40

Specification.where(null) works just fine. It is annotated with @Nullable and the implementation handles null values as it should.

The problem is that you are using the and method as if it would modify the Specification, but it creates a new one. So you should use

spec = spec.and( ... );
Sign up to request clarification or add additional context in comments.

2 Comments

Let's say I have 5 fields, but because they all are null, the spec is left with the value of Specification.where(null). Question: is there a way to check that spec equals to Specification.where(null)
@IlyaSerebryannikov please don't ask new questions in comments, ask them in questions.
1

Specification.where() is marked for removal.

Another way is to have a lambda function:

Specification<Foo> spec = (root, query, cb) -> null;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.