Listagem com filtragem dinâmica e Paginação usando o Spring Boot com Java

 Um caso bem comum atualmente é a necessidade de se implementar listagem e de ser necessario que os filtros sejam dinâmicos, para implementar esta solução iremos uitlizar o  Spring Data Jpa em específico neste caso fazendo uso do JpaRepository e do JpaSpecificationExecutor, além de implementarmos mais duas classes sendo uma para os critérios da busca (Filtros) e outra para gerar o Predicate de forma genérica atravéz de um builder.

Para começar iremos criar o recurso em nosso controller para receber os valores do filtro e então chamar o service responsável pela busca, como exemplo o da imagem a baixo.


Controller

Como pode ser observado na imagem acima o controller esta chamando uma classe e fazendo build dos valores que vieram atravéz dos filtros, ficando então neste objeto salvo os dados que serão usados na busca, imagem da classe usada neste ponto.


EventSearchCriterios

Após a construção do objeto de search o service é chamado passando ele como parâmetro, neste service em questão não a nada expecifico ele apenas faz o papel de intermediario entre o controller e o filtro resposável por acessar a camada de dados.


Service

Como dito antes o service faz a chamada ao método de filtro de acesso aos dados e devolve o resultado ao controller, o método chamado nesta implementação é o findAllByFilter, ele recebe como parâmetro o eventSearchCriterios e então começa a chamar os demais métodos para que a busca seja realizada corretamente.


EventSearchFilters

Como pode ser observado no método a primeira ação realizada é chamar o eventRepository esta interface estende o JpaRepository e JpaSpecificationExecutor que são peças chave para a consulta.

Repository


A inteface repository é uma classe de implementação simples suas extensões já trazem por baixo do capo tudo que precisamos, claro em alguns casos é preciso adicionar algumas novas assinaturas como por exemplo findByName(). O JpaRepository consegue reconhecer sem nenhuma implementação o que precisa ser feito mas em alguns casos é ainda preciso adicionar uma query acima da assinatura do método, bom com isso dito voltamos a classe principal onde podemos ver que é possível recuperar atravéz do finAll os valores root, criteriaQuery, criteriaBuilder, que são muito importantes para a continuidade da implementação. 




Seguindo para o próximo passo vemos que os valores recuperados assim como o objeto que contém os filtros são passados para o método filtrar, este método ira montar os Joins e os Predicates que serão usado na consulta.


Filtrar

Como pode ver dentro do método filtrar vemos a chamada a biblioteca PredicateSearchBuilder onde implementei de forma dinâmica a filtragem para que gere o Predicate você pode baixar essa versão da biblioteca aqui PredicateSearchBuilder este link é provisório pois logo irei publicar no Maven Repository para que fique melhor de utiliza-la. 


PredicateSearchBuilder

Para usar a biblioteca e gerar nosso predicate de forma dinâmica precisamos fazer a chamada com o new PredicateSearchBuilder() passando como parâmetro para o construtor o CriteriaBuilder, em seguida então começamos a buildar de acordo com a necessidade do filtro utilizando "." e escolhendo o método que desejamos filtrar, como pode ver no exemplo acima temos o equalIntegerRoot este método como o nome indica ira criar um filtro para igualar uma consulta de um inteiro utilizando o root, existe também o equalIntegerJoin que faz o mesmo porém com um join caso precise comparar em uma tabela ligada, como parâmetro ira receber além do Root ou Join, a coluna a ser filtrada, o valor a ser filtrado (Este valor chega até nos atravéz do objeto com os valores de filtro montado no controller neste caso o EventSearchCriterios) e um boolean que esta reservado para o critério do filtro, por exemplo digamos que eu queira que o filtro seja aplicado apenas se o valor for maior que 0, afinal o usuário pode não ter selecinado esse filtro, ou se tratando de algo específico que somente filtre se for 1 ou 5, vai depender da necessidade da implementação mas isso deixa muitas possibilidades ao desenvolvedor, por fim chamamos o .build() salvamos o valor em uma variavel e retornamos ao método principal para continuar o processo.

Voltando ao método filtrar já com nosso Predicate populado podemos opcionalmente ordenar a consulta usando o criteriaQuery.orderBy

criteriaQuery

Damos então return setando o Predicate e passamos os valores para a paginação e por fim retornamos nossa lista.


return

Com isso temos nossa filtragem dinâmica, obrigado por ler até aqui!! Se tiver alguma dúvida, dica ou sugestão deixe nos comentarios.


💻 É isso, bora codar!💻

Comentários

Postagens mais visitadas