Interface 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 consultas 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();
Quando utilizamos o método getResultList da interface Query é retornado uma lista de entidades.
Consulta que retorna um único objeto:
Query query = em.createNamedQuery("Emprestimo.qtdEmprestimosPorLivro");
Long quantidade = (Long) query.getSingleResult();
Quando utilizamos 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 DAO que executa as operações: salvar, alterar, remover, consultar por id, consultar todos os empréstimos, consultar a quantidade de empréstimos de um livro e consultar todos os empréstimos de um livro.
package pbc.jpa.exemplo.dao;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import pbc.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();
  }
}