Spring Data JPA query , filter ? search engine ? JPQL?

Mazur Paweł :

I have problem with writing a query in JPA repository because I have a method searching for fathers basing on their name, surname etc.

@Query("select * from father where # ???")
List<Father> searchFather(@Param("fatherBirthDate") LocalDate fatherBirthDate,
                          @Param("fatherFirstName") String fatherFirstName,
                          @Param("fatherSurName") String fatherSurName)

And I want to make a 'Search Engine' returning fathers but like this:

  • When I do not provide any parameters, the repository will return all fathers
  • When I provide for example father name, the query returns a list of father with the provided name

To better explain:

|FATHER_NAME|FATHER_SURNAME|FATHER_BIRTH_DATE|
|JON        |SNOW          |1992-01-01       |
|JON        |ALBY          |1993-01-01       |
|JACK       |ADLEY         |1995-01-01       |
|HARRY      |COLBY         |1996-01-01       |
  • When I provide nothing query return all fathers
  • When I provide father name "JON", I expect JON SNOW and JON ALBY
  • When I provide surname "COLBY", query will return HARRY COLBY

I trying million times, but I cannot write a query that will return all fathers when I do not provide any parameters and reduce list of found fathers when I provide some parameters.

zpavel :

The simplest way to provide a dynamic search with Spring Boot is to use specifications.

Enable search by specification in your repository class :

public interface FatherRepository extends JpaRepository<Father, Long>, JpaSpecificationExecutor<Father> {}

Create specification class :

public class FatherSpecifications {
    public static Specification<Father> hasBirthdate(LocalDate birthdate) {
        return (father, cq, cb) -> Optional.ofNullable(birthdate).map(b -> cb.equal(father.get("birthdate"), b)).orElse(null);
    }

    public static Specification<Father> firstnameLike(String firstname) {
        return (father, cq, cb) -> Optional.ofNullable(firstname).map(f -> cb.like(father.get("firstname"), "%" + f + "%")).orElse(null);
    }

    public static Specification<Father> surnameLike(String surname) {
        return (father, cq, cb) -> Optional.ofNullable(surname).map(s -> cb.like(father.get("surname"), "%" + s + "%")).orElse(null);
    }
}

Then you can search anywhere in code (where FatherRepository is autowired) with :

List<Father> fathers = fatherRepository.findAll(Specification.where(FatherSpecifications.hasBirthdate(birthdate)).and(FatherSpecifications.firstnameLike(firstname)).and(FatherSpecifications.surnameLike(surname)));

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=161764&siteId=1