Suppose I have an Employee class with multiple fields like name, age, salary, designation, joiningDate, gender and many more. Now, how could I apply filtering with many such parameters? There could be many combinations possible in such cases. (For Eg. if I want to have 6 filters, then there can be total of 6! = 720 combinations possible!!!)
For only 2,3 parameters, like age, salary, name; then I could write multiple if cases like:
if(age!=null && name==null && salary==null)
{
findByAge
}
if(age==null && name!=null && salary==null)
{
findByName
}
if(age!=null && name!=null && salary==null)
{
findByAgeAndName
}
etc. like these with help of Spring Data JPA. But how to handle more parameters since combinations would increase with each RequestParams?
CodePudding user response:
What you are looking for is a multi criteria query. You can use the very simple Example API
In your case, the code sould look something like this :
You will create an entity with the builder pattern. Lombok can help you in this step :
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "employee")
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name")
private String name;
@Column(name = "age")
private int age;
// your other fields
}
Then you can call your method :
Employee employee = Employee
.builder()
.name(nameValue)
.age(ageValue)
.build();
return repository.findAll(Example.of(employee));
You will find a full example here.
CodePudding user response:
You should not write many condition and/or to call the function. It's hard to combine many condition.
In this case i often write the query which will append the condition if parameter is not null or if specify.
Here is my way:
String query = "select * from table where 1=1";
Map<String,Object> params = new HashMap<>();
if(filter1!=null){
query = " and field1 = :filter1";
params.put("filter1",filter1);
}
if(filter2!=null){
query = " and field2 = :filter2";
params.put("filter2",filter2);
}
dao.execute(query,params);
The condition null is not required, you can adapt it. In case you don't want to have many arguments in your function. You can create object/context/map to hold all filters.
PS: I use String for readability, you should use StringBuilder.
For spring-jpa: ExampleMatcher can do the same.
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#query-by-example.matchers
CodePudding user response:
A solution is to have a single method, and make parameters "optional" by managing null values in the query :
@Query("""
select a from YourEntity a where
(?1 is null or a.name = ?1)
and (?2 is null or a.age= ?2)
and (?3 is null or a.salary = ?3)
and (?4 is null or a.description = ?4)
and (?5 is null or a.joiningDate = ?5)
and (?6 is null or a.gender = ?6)
""")
List<YourEntity> findFiltered(String name, Integer age, Float salary, String designation, LocalDateTime joiningDate, String gender)