1. Poderia ser feito com @Query?? Algum risco de segurança?

    Resolvida
    Boa noite, entendo o conteúdo da aula e a forma de mostrar vários conteúdos, porém achei um pouco complexo tanta coisa para um filtro e tentei simplificar rsrsrs. Tentei criar uma alternativa e utilizei querys ao invés do Criteria. Gostaria de pedir que desse uma olhada e criticasse a minha ideia... Está errado? Poderia utilizar o que fiz no "mundo" real? Minha aplicação corre algum risco de segurança, como SQL Injection ou algo assim? Desde já muito obrigado e o curso é show... Segue abaixo a minha implementação, a classe de serviço e de recurso ficaram iguais, também criei uma classe filter e só a consulta que fiz assim... package br.com.deab.deabmoney.api.repository; public interface LancamentoRepository extends JpaRepository<Lancamento, Long>{ public static final String LANCAMENTO_FILTER = "select la from lancamento la where descricao like %?1% or (dataVencimento between ?2 and ?3)"; @Query(LANCAMENTO_FILTER) public List<Lancamento> findByLancamentoFilter(String descricao, LocalDate dataVencimentoDe, LocalDate dataVencimentoAte ); }
    6 Respostas
  2. Olá Paulo! Não tem problema nenhum em utilizar o @Query, em alguns casos realmente é até melhor. Não há perigo de segurança também, pode ficar tranquilo. Uma sugestão, que talvez ajude a facilitar a leitura ainda mais, seria nomear os parâmetros da sua consulta, então ao invés de você fazer:
    select la from lancamento la where descricao like %?1% or (dataVencimento between ?2 and ?3)
    Pode fazer assim:
    select la from lancamento la where descricao like %:descricao% or (dataVencimento between :dataDe and :dataAte)
    Nomeando seus parâmetros, fica mais legível e evita se perder na posição dos mesmos. Para preenchê-los, é necessário anotar os argumento do seu método com @Param:
    @Query(LANCAMENTO_FILTER)
     public List<Lancamento> findByLancamentoFilter(@Path("descricao") String descricao, @Path("dataDe") LocalDate dataVencimentoDe, @Path("dataAte") LocalDate dataVencimentoAte );
    }
    Outro ponto agora, é se essa abordagem é boa para o que foi proposto na aula, e da forma como está eu diria que não atende a necessidade. A ideia do método mostrado na aula é que filtro seja dinâmico, então essa query deve funcionar se o usuário informar a descrição ou não, se o usuário informar período ou não, se informar os dois ao mesmo tempo, ou nenhum. Na query que você elaborou, não dá essa flexibilidade, pois sempre aplicará os filtros, atendendo à um ou outro. E se informar os dois, devido ao OR, ele vai trazer registros que atendem apenas a descrição e não respeitará o período, e vice-versa. Mas existem outras formas de contornar este problema, inclusive usando @Query, por exemplo:
    select la from lancamento la where (:descricao is null or descricao like %:descricao%) and ((:dataDe is null and :dataAte is null) or (dataVencimento between :dataDe and :dataAte))
    Neste caso, verificamos se o parametro recebido é null ou não, se não for, aplicará no filtro.
  3. Correção! Desculpe Paulo, eu disse que você precisa utilizar a anotação @Param, mas no exemplo esrevei @Path, o certo é @Param mesmo:
    @Query(LANCAMENTO_FILTER)
     public List<Lancamento> findByLancamentoFilter(@Param("descricao") String descricao, @Param("dataDe") LocalDate dataVencimentoDe, @Param("dataAte") LocalDate dataVencimentoAte );
    }
  4. Entendido muito obrigado.
  5. certo pelo que entendi esse processo substitui a criação da classe filter certo?
  6. Olá Emerson! Basicamente sim, você ainda pode usar a classe filter, mas a consulta neste caso será feita com código JPQL ao invés do uso de Criteria. Uma melhoria na consulta:
    select la 
      from lancamento la 
     where (:descricao is null or descricao like %:descricao%) 
       and (:dataDe is null or dataVencimento >= :dataDe) 
       and (:dataAte is null or dataVencimento <= :dataAte)
    Dessa forma, os parametros dataDe e dataAte ficam independentes.
  7. Entendi William , valeu!