I want to have a spring data repository interface that takes two parameters. Is there a way to make it have the following behaviour?
MyObject findByParameterOneAndParameterTwo( String parameterOne, String parameterTwo);
If both parameters have a value, I would like it to behave normally and do an "AND" for both values.
If for example the second parameter is null, then it would search only by ParameterOne
Any suggestions?
The JPA specification defines that during ordering, NULL values shall be handled in the same way as determined by the SQL standard. The standard specifies that all null values shall be returned before or after all non-null values. It's up to the database to pick one of the two options.
You can ignore null fields at the class level by using @JsonInclude(Include. NON_NULL) to only include non-null fields, thus excluding any attribute whose value is null. You can also use the same annotation at the field level to instruct Jackson to ignore that field while converting Java object to json if it's null.
Following example shows how to use IS NULL to find properties values which have not been set.
The normal behavior is indeed returning an empty list if no results are found. If a List<Object> is the return value of the method in the defined interface, the method should never return Null . The problem is that a parameter is given to the method and is not used anywhere in the Query.
I'm not sure it is possible with repository methods naming but you can use @Query
like
(:parameterOne is null or parameter1 = :parameterOne) and (:parameterTwo is null or parameter2 = :parameterTwo)
One solution that's missing here is Spring Data JPA's Query By Example feature and leverage the ExampleMatcher#ignoreNullValues
, which is built exactly to solve this problem. A custom query and query builder are not necessary.
This Spring Data query:
ExampleMatcher matcher = ExampleMatcher.matching().withIgnoreNullValues(); Example<MyObject> exampleQuery = Example.of(new MyObject("foo", null), matcher); List<MyObject> results = repository.findAll(exampleQuery);
Yields a query that looks like:
select * from myObject where parameter1 = "foo"
While the following:
ExampleMatcher matcher = ExampleMatcher.matching().withIgnoreNullValues(); Example<MyObject> exampleQuery = Example.of(new MyObject("foo", "bar"), matcher); List<MyObject> results = repository.findAll(exampleQuery);
Yields:
select * from myObject where parameter1 = "foo" and parameter2 = "bar"
Very cool!
Note: One thing you'll have to do to your Repository
interface is add the QueryByExample
interface. You can do this either by extending the QueryByExample
interface directly, or implicity via the JpaRepository
:
public interface MyObjectRepository extends JpaRepository<MyObject, Long> {}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With