If you don't want to use QueryDSL, you'll have to write your own specifications. First of all, you need to extend your repository from JpaSpecificationExecutor
like you did. Make sure to add the generic though (JpaSpecificationExecutor<Some>
).
After that you'll have to create three specifications (one for each column), in the Spring docs they define these specifications as static methods in a class. Basically, creating a specification means that you'll have to subclass Specification<Some>
, which has only one method to implement, toPredicate(Root<Some>, CriteriaQuery<?>, CriteriaBuilder)
.
If you're using Java 8, you can use lambdas to create an anonymous inner class, eg.:
public class SomeSpecs {
public static Specification<Some> withAddress(String address) {
return (root, query, builder) -> {
// ...
};
}
}
For the actual implementation, you can use Root
to get to a specific node, eg. root.get("address")
. The CriteriaBuilder
on the other hand is to define the where clause, eg. builder.equal(..., ...)
.
In your case you want something like this:
public class SomeSpecs {
public static Specification<Some> withAddress(String address) {
return (root, query, builder) -> builder.equal(root.get("address"), address);
}
}
Or alternatively if you want to use a LIKE
query, you could use:
public class SomeSpecs {
public static Specification<Some> withAddress(String address) {
return (root, query, builder) -> builder.like(root.get("address"), "%" + address + "%");
}
}
Now you have to repeat this for the other fields you want to filter on. After that you'll have to use all specifications together (using and()
, or()
, ...). Then you can use the repository.findAll(Specification)
method to query based on that specification, for example:
public List<Some> getSome(String address, String name, Date date) {
return repository.findAll(where(withAddress(address))
.and(withName(name))
.and(withDate(date));
}
You can use static imports to import withAddress()
, withName()
and withDate()
to make it easier to read. The where()
method can also be statically imported (comes from Specification.where()
).
Be aware though that the method above may have to be tweaked since you don't want to filter on the address field if it's null
. You could do this by returning null
, for example:
public List<Some> getSome(String address, String name, Date date) {
return repository.findAll(where(address == null ? null : withAddress(address))
.and(name == null ? null : withName(name))
.and(date == null ? null : withDate(date));
}