17 de abril de 2011

JPA 2.0: Utilizando os NamedQuery

Segundo a especificação do JEE 6, NamedQuery é definida como:
"Specifies a static, named query in the Java Persistence query language. Query names are scoped to the persistence unit. The NamedQuery annotation can be applied to an entity or mapped superclass."
Traduzindo... NamedQuery's são consultas Java Persistence estáticas e pré-definidas.
Como são elas?
Vamos usar como exemplo a postagem de como gerar classes anotadas a partir do banco de dados com o NetBeans, ao gerar as classes a partir do banco, o NetBeans já gera algumas NamedQuery's, logo abaixo da anotação @Entity, por exemplo vou pegar as NamedQuery's geradas sobre a classe Categoria.
@NamedQueries({
    @NamedQuery(name = "Categoria.findAll", query = "SELECT c FROM Categoria c"),
    @NamedQuery(name = "Categoria.findByCodigo", query = "SELECT c FROM Categoria c WHERE c.codigo = :codigo"),
    @NamedQuery(name = "Categoria.findByNome", query = "SELECT c FROM Categoria c WHERE c.nome = :nome")})
Nada lhe impede de criar novas consultas, ou alterar o name das mesmas.
Como utilizá-las?
Aproveitando o projeto de gerar classes anotadas a partir do banco de dados (link acima), vou usar as NamedQuery de Categoria (postada logo acima). Só irei mostrar os métodos da minha classe DAO (tem vários exemplos de CRUD no blog...). Não tem muito o que explicar porque o método por sí só é bem claro.
Primeiro vou usar a NamedQuery de listar todas as categorias que é a: Categoria.findAll
public List<Categoria> listar(){
 List<Categoria> categorias = null;
 try {
  categorias = em.createNamedQuery("Categoria.findAll")
   .getResultList();
 } catch (Exception e) {
  e.printStackTrace();
 }
 return  categorias;
}
O meu em é o meu EntityManager, dele eu uso o método createNamedQuery, e passo o nome do NamedQuery que está lá na minha Categoria.

public Categoria buscar(Integer codigo){
 Categoria categoria = null;
 try {
  categoria = (Categoria) em.createNamedQuery("Categoria.findByCodigo")
   .setParameter("codigo", codigo)
   .getSingleResult();
 } catch (Exception e) {
  e.printStackTrace();
 }
 return categoria;
}
Para selecionar apenas um resultado não é muito diferente, basta apenas setar os parameters, que são aqueles precedidos por : (dois pontos), nesse caso é o codigo. E para pegar um resultado eu uso o getSingleResult().

Dá pra ver que não é muito complicado utilizar os NamedQuerys...
Detalhe, caso haja mais parâmetros para setar em um namedQuery, basta ir concatenando um ao outro, por exemplo, suponhamos que o namedQuery usado abaixo tivesse mais um parametro que seria nome, basta fazer isso:
categoria = (Categoria) em.createNamedQuery("Categoria.findByCodigo")
    .setParameter("codigo", codigo)
    .setParameter("nome", "Andreia")
    .getSingleResult();
}

E assim, ficamos por aqui com mais uma postagem ;)

11 comentários:

  1. Muito bom. Ajudou muito. Senhorita Andii facilitando minha vida.

    ResponderExcluir
  2. Muito show!! Mas tenha uma dúvida. Posso utilizar @NamedQuery para obter uma lista do tipo: Tenho uma entidade com os dias trabalhados em um projeto, dai eu preciso criar uma lista com o total trabalhado em cada projeto.
    @NamedQueries({
    @NamedQuery(name="DiasFA.gerencialProjeto",
    query="select projeto.descricao , sum(diasfa.hrtotal)"
    + "from DiasFA diasfa, FichaAprop fa, Usuario user, Projeto projeto "
    + "where diasfa.fichaaprop = fa and fa.usuario = user and fa.projeto = projeto"
    + " group by projeto.descricao ")
    })

    ResponderExcluir
  3. Ola Cristiano!
    Você pode usar as NamedQuery para fazer a consulta que necessitar, a utilidade dela é que vc pode reaproveitar a mesma consulta em outras classes, e se precisar alterar, só altera em um unico lugar.

    ResponderExcluir
  4. Tópico bem esclarecedor. Se não fosse ele, eu não teria conseguido. Obrigado Andii!

    ResponderExcluir
  5. Que bom que tenha te ajudado Henrique! :)

    ResponderExcluir
  6. Olá, sou iniciante em java e estou com dificuldades em preencher jcombobox através de namedQuery, No netbeans ao gerar uma tela ele já cria o bean com estas namedQuery, gostaria se possivel uma orientação para preencher jcombobox em cascata passando parametros com namedquery,isto é possivel? . Parabens pelas dicas...

    ResponderExcluir
  7. Boa noite andii.brunetta
    Estou com a seguinte dúvida: Realizar update por meio de uma named query é correto?

    @NamedQuery(name = "Alerta.updateInativaAlerta", query = "UPDATE Alerta a SET a.status = 0 WHERE a.idalerta =:idalerta ")

    ResponderExcluir
    Respostas
    1. Olá! Pergunta complicada rsrs porque eu sempre uso o em.merge(objeto) pra atualizar os dados, não precisei usar via query. Eu aconselho usar o merge, a menos que seja uma regra usar query para o seu projeto.

      Excluir
  8. Muito obrigado pela explicação, me ajudou muito.

    ResponderExcluir
  9. Muito bom, o código bem limpo e direto!!!

    ResponderExcluir
  10. Olá, como filtrar uma tabela por exemplo cidades que tem uma chave estrangeira Estado ?

    ResponderExcluir

Deixe seu comentário... ;)