Home > OS >  Global Filter with JPQL Spring
Global Filter with JPQL Spring

Time:03-03

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));
}
  • Related