I'm doing some projects a many them ask to do a global filter, my question is is there any chance to do a global filter without use to many if to check if the user add that filter or no? here an example of one of my projects: in repository I add this code:
@Query("from students s join Class_Room c on s.classRoom.id=c.id join teachers t on t.id=c.id "
"where c.name= :className AND t.subject= :subject AND s.name= :name")
List<Student> studentClassProf(@Param("className") String className, @Param("subject") String subject, @Param("name") String name);
@Query("from students s join Class_Room c on s.classRoom.id=c.id join teachers t on t.id=c.id "
"where c.name= :className AND t.subject= :subject")
List<Student> studentClassProf(@Param("className") String className, @Param("subject") String subject);
And in my controller class I using this:
@GetMapping("/globalSearch")
public ResponseEntity<String> globalSearch(String studentName, String teacherName, String className, String subject) throws MyNotFoundException {
if (studentName != null && teacherName != null && className != null && subject != null) {
studentRepo.studentClassProf(className, subject, studentName);
}
if (studentName == null && teacherName != null && className != null && subject != null) {
studentRepo.studentClassProf(className, subject);
}
....
So what can I do without add a lot of if to check if the field is null or not or I can't to do nothing to solve and I always have to write a lot of if block?
CodePudding user response:
You could use JpaSpecificationExecutor<T>
.
In order to use it, you have to extend your repository interface from JpaSpecificationExecutor<T>
:
public interface StudentRepository extends JpaRepository<Student, UUID>,
JpaSpecificationExecutor<Student> {}
Then you can make a method that generates a specification based on parameters or a filter class.
public class StudentSpecification {
private static Specification<Student> getStudentFilterSpecification(String studentName, String teacherName, String className, String subject) {
return (root, query, criteriaBuilder) -> {
Predicate predicate = criteriaBuilder.conjunction();
// Condition student name.
if (Objects.nonNull(studentName)) {
predicate = criteriaBuilder.and(predicate, criteriaBuilder
.equal(root.get("studentName"), studentName));
}
// Condition teacher name.
if (Objects.nonNull(teacherName)) {
predicate = criteriaBuilder.and(predicate, criteriaBuilder
.equal(root.get("teacherName"), teacherName));
}
// Condition class name.
if (Objects.nonNull(className)) {
predicate = criteriaBuilder.and(predicate, criteriaBuilder
.equal(root.get("className"), className));
}
// Condition subject.
if (Objects.nonNull(subject)) {
predicate = criteriaBuilder.and(predicate, criteriaBuilder
.equal(root.get("subject"), subject));
}
return predicate;
};
}
}
Now you can send search request with specification.
@GetMapping("/globalSearch")
public ResponseEntity<String> globalSearch(
String studentName, String teacherName, String className, String subject)
throws MyNotFoundException {
studentRepo.findAll(StudentSpecification
.getStudentFilterSpecification(studentName,
teacherName, className, subject));
}