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 |
C
om 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
Postar um comentário