Using Spring JPA Data Specification is a really good way to solve this issue.
This solution should work for all data types and allow all DB functions (greater/less/like/equal/or/not/etc).
I personally find that encapsulating the business logic/criteria builder into these makes the service code much more readable, especially if you give good names to your specification methods. You can even have private methods that your public methods use to make your Specification code more readable!
For OP's example, create a class with these methods.
public static Specification<Entity> equalsParameterOne(String parameterOne){
//If the specification is null it will be excluded from the SQL and ignored
if(parameterOne == null || parameterOne.length = 0) return null;
return (root, query, cb) -> cb.equal(root.get("fieldOne"), parameterOne);
}
public static Specification<Entity> equalsParameterTwo(String parameterTwo){
//If the specification is null it will be excluded from the SQL and ignored
if(parameterTwo== null || parameterTwo.length = 0) return null;
return (root, query, cb) -> cb.equal(root.get("fieldTwo"), parameterTwo);
}
Then in your service code where you use the jpaRepo you can use with findAll() like this.
//Be careful with your parenthesis
Specification<Entity> customDynamicSpecs =
Specification
.where(equalsParameterOne(criteria.getParamOne()))
.and(equalsParameterTwo(criteria.getParamTwo()));
//.or().not()
//... as many as you want.
//findAll() can take Pageable or Sort as 2nd argument for extra functionality.
repo.findAll(customDynamicSpecs);
To make this work, you must declare your repo extends JpaSpecificationExecutor as well as make a few more static imports than anyone should probably be comfortable with. But again, for me, the readable code wins out.