JPA - Examinar a linguagem de consulta do Java Persistence API (JPQL)

Interface javax.persistence.Query

A interface Query é responsável por:

  • Fazer as consultas.
  • Executar updates.
  • Passar parâmetros para consulta.
  • Pegar um simples resultado.
  • Pegar uma lista de resultados.

Para executar uma consulta utilizamos a interface javax.persistence.Query e criamos uma Query a partir do EntityManager, exemplo:

public List<Emprestimo> consultarTodos() {
  EntityManager em = getEntityManager();
  Query query = em.createNamedQuery("Emprestimo.consultarTodos");
  return query.getResultList();
}

Nesse exemplo estamos utilizando a EntityManager para criar uma consulta nomeada através do método getNamedQuery e passamos o nome da consulta “Emprestimo.consultarTodos” declarado na entidade.

Através da EntityManager podemos utilizar o método createQuery para criar a consulta e já declarar todo o código dela, podendo criar uma consulta um pouco mais personalizada:

Query query = em.createQuery("SELECT c FROM Cliente c");

Também podemos criar uma consulta nativa para uma base de dados especifica:

Query query = em.createNativeQuery("SELECT * FROM Cliente");

Para executar uma consulta podemos ter como resposta um simples objeto ou uma lista de objetos.

Neste exemplo vamos executar uma consulta que retorna uma lista de objetos:

Query query = em.createNamedQuery("Cliente.consultarTodosClientes");
List<Cliente> clientes = (List<Cliente>) query.getResultList();

O método getResultList() da interface Query é retornado uma lista de entidades.

Consulta que retorna um unico objeto:

Query query = em.createNamedQuery ("Emprestimo.qtdEmprestimosPorLivro");
Long quantidade = (Long) query.getSingleResult();

O método getSingleResult() da interface Query é retornado apenas um objeto. Este método pode lançar também a exceção javax.persistence.NoResultException quando a consulta não retorna nenhum resultado ou também uma exceção javax.persistence.NonUniqueResultException quando você espera retornar apenas um objeto e a consulta acaba retornando mais de um objeto.

Através da interface Query podemos passando parâmetros para a consulta através do método setParameter:

public List<Emprestimo> consultarTodosPorTituloLivro(String tituloLivro) {
  EntityManager entityManager = getEntityManager();
  Query query = entityManager.createNamedQuery("Emprestimo.consultarTodosPorTituloLivro");

  query.setParameter("titulo", tituloLivro);

  return query.getResultList();
}

Exemplo de classe Emprestimo de livros onde são declarados os atributos referentes ao emprestimo e também declarados todas as NamedQueries que iremos utilizar para consultar as informações de emprestimos.

package br.universidadejava.jpa.exemplo.modelo;

import java.io.Serializable;
import java.util.Date;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

/**
 * Classe utilizada para representar o emprestimo de um livro para um cliente.
 */
@NamedQueries({
  @NamedQuery(name = "Emprestimo.consultarTodos",
              query= "SELECT e FROM Emprestimo e"),

  @NamedQuery(name = "Emprestimo.qtdEmprestimosPorLivro",
              query = " SELECT count(e) " +
                      " FROM Emprestimo e " +
                      " WHERE e.livro.id = :id "),

  @NamedQuery(name = "Emprestimo.consultarTodosPorTituloLivro",
              query = " SELECT e " +
                      " FROM Emprestimo e, Livro l " +
                      " WHERE e.livro.id = l.id " +
                      " AND l.titulo LIKE :titulo ")
})
@Entity
public class Emprestimo implements Serializable {
  private static final long serialVersionUID = 7516813189218268079L;

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;
  @ManyToOne(cascade=CascadeType.REFRESH, fetch=FetchType.EAGER)
  private Livro livro;
  @ManyToOne(cascade=CascadeType.REFRESH, fetch=FetchType.EAGER)
  private Cliente cliente;
  @Temporal(TemporalType.DATE)
  private Date dataEmprestimo;
  @Temporal(TemporalType.DATE)
  private Date dataDevolucao;

  public Cliente getCliente() { return cliente; }
  public void setCliente(Cliente cliente) { this.cliente = cliente; }
  public Date getDataDevolucao() { return dataDevolucao; }
  public void setDataDevolucao(Date dataDevolucao) {
    this.dataDevolucao = dataDevolucao;
  }
  public Date getDataEmprestimo() { return dataEmprestimo; }
  public void setDataEmprestimo(Date dataEmprestimo) {
    this.dataEmprestimo = dataEmprestimo;
  }
  public Long getId() { return id; }
  public void setId(Long id) { this.id = id; }
  public Livro getLivro() { return livro; }
  public void setLivro(Livro livro) { this.livro = livro; }
}

Exemplo de classe DAO que executa as operações: salvar, alterar, remover, consultar por id, consultar todos os emprestimos, consultar a quantidade de emprestimos de um livro e consultar todos os emprestimos de um livro.

package br.universidadejava.jpa.exemplo.dao;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import br.universidadejava.jpa.exemplo.modelo.Emprestimo;

/**
 * Classe utilizada para representar as operações sobre a entidade emprestimo.
 */
public class EmprestimoDAO {
  public EntityManager getEntityManager() {
    EntityManagerFactory factory = null;
    EntityManager entityManager = null;
    try {
      factory = Persistence.createEntityManagerFactory("UnidadeDePersistencia");
      entityManager = factory.createEntityManager();
    } finally {
      factory.close();
    }
    return entityManager;
  }

  public Emprestimo consultarPorId(Long id) {
    EntityManager entityManager = getEntityManager();
    Emprestimo emprestimo = null;
    try {
      emprestimo = entityManager.find(Emprestimo.class, id);
    } finally {
      entityManager.close();
    }
    return emprestimo;
  }

  public Emprestimo salvar(Emprestimo emprestimo) {
    EntityManager entityManager = getEntityManager();
    try {
      entityManager.getTransaction().begin();
      if(emprestimo.getId() == null) {
        entityManager.persist(emprestimo);
      } else {
        entityManager.merge(emprestimo);
      }
      entityManager.flush();
      entityManager.getTransaction().commit();
    } catch (Exception ex) {
      entityManager.getTransaction().rollback();
    } finally {
      entityManager.close();
    }
    return emprestimo;
  }

  public void apagar(Long id) {
    EntityManager entityManager = getEntityManager();
    try {
      entityManager.getTransaction().begin();
      Emprestimo emprestimo = entityManager.find(Emprestimo.class, id);
      entityManager.remove(emprestimo);
      entityManager.flush();
      entityManager.getTransaction().commit();
    } catch (Exception ex) {
      entityManager.getTransaction().rollback();
    } finally {
      entityManager.close();
    }
  }

  public List<Emprestimo> consultarTodos() {
    EntityManager entityManager = getEntityManager();
    Query query = entityManager.createNamedQuery("Emprestimo.consultarTodos");
    return query.getResultList();
  }

  public Long getQtdEmprestimosPorLivro(Long id) {
    EntityManager entityManager = getEntityManager();
    Query query = entityManager.createNamedQuery("Emprestimo.qtdEmprestimosPorLivro");
    query.setParameter("id", id);
    return (Long) query.getSingleResult();
  }

  public List<Emprestimo> consultarTodosPorTituloLivro(String tituloLivro) {
    EntityManager entityManager = getEntityManager();
    Query query = entityManager.createNamedQuery("Emprestimo.consultarTodosPorTituloLivro");
    query.setParameter("titulo", tituloLivro);
    return query.getResultList();
  }
}