Академический Документы
Профессиональный Документы
Культура Документы
Por padro, todo banco de dados relacional aceita a Structured Query Language (SQL) para realizar consultas e manipulaes em modelos relacionais. Quando adotamos o JPA, uma das coisas que buscamos nos distanciar o mximo possvel do modelo relacional e focar exclusivamente no modelo orientado a objetos e seus estados:
Alm disso, o SQL nos obriga a conhecer bem o modelo de dados, e podemos facilmente notar isso analisando um simples cdigo de consulta que usvamos quando trabalhvamos diretamente com a API do JDBC.
Repare que no cdigo abaixo conhece o nome da tabela e das colunas do modelo relacional:
public List<Conta> consultaContasPorTitularPaginada (String titular, int posicaoInicial, int qntRegistros) { String sql = "SELECT * FROM conta WHERE titular LIKE ? LIMIT ?,?"; try { PreparedStatement stmt = conexao.prepareStatement(sql); stmt.setString(1, "%"+titular+"%"); stmt.setInteger(2, posicaoInicial); stmt.setInteger(3, qntRegistros) ResultSet rs = stmt.executeQuery(); List<Conta> contas = new ArrayList<Conta>(); while (rs.next()) { Conta conta = new Conta(); conta.setId(Long.valueOf(rs.getString("id"))); conta.setAgencia(rs.getString("agencia")); conta.setBanco(rs.getString("banco")); conta.setNumero(rs.getString("numero")); conta.setTitular(rs.getString("titular")); contas.add(conta); } rs.close(); stmt.close(); } catch (SQLException ex) { System.out.println("Erro na consulta da conta."); } return contas; }
Alm de termos que escrever uma String com o SQL, que ser enviada ao banco, precisamos saber o nome da tabela e de suas colunas. E mais, ao recebermos a resposta da consulta ao banco, via ResultSet, precisamos ainda passar essas informaes para um objeto e retorn-lo posteriormente. Todo o mapeamento entre o mundo relacional e OO feito manualmente.
Faremos primeiro uma consulta simples que retornar todas as movimentaes de uma determinada conta. Como j sabemos vamos criar o EntityManager atravs da classe auxiliar JPAUtil. Alm disso, vamos instanciar uma conta que possui a id 2 (essa id deve existir no banco):
Depois disso vamos usar o mtodo createQuery(..) do EntityManager passando para ele um cdigo JPQL. Utilizamos a clausula select-from parecida com SQL mas aqui o alvo da consulta no a tabela no banco mas sim a classeMovimentacao do nosso modelo OO. Adicionamos o alias m para facilitar a digitao:
A clausula where filtar a consulta. Repare que filtramos por m.conta.id, isto pela id da conta da movimentao. Por fim concatenamos a id da conta o JPQL:
retorno
do
um
objeto
do
tipo javax.persistence.Query. Atravs desse objeto, podemos solicitar que o resultado seja uma lista de objetos, em nosso caso, de movimentaes, atravs do mtodogetResultList(). Depois s iterar na lista.
package br.com.caelum.financas.teste; // imports omitidos public class TestaConsulta { public static void main(String[] args) { EntityManager manager = new JPAUtil().getEntityManager(); Conta conta = new Conta(); conta.setId(2); Query query = manager.createQuery("select m from Movimentacao m where m.conta.id=" + conta.getId()); List<Movimentacao> movimentacoes = query.getResultList(); for (Movimentacao m : movimentacoes) { System.out.println("\nDescricao ..: " + m.getDescricao()); System.out.println("Valor ......: R$ " + m.getValor()); } }
Recapitulando,
criamos
um
objeto
do
do
mtodo createQuery(..) do EntityManager que recebeu como parmetro um JPQL. Apesar de lembrar um SQL a consulta sobre nossas classes do modelo, classes que podemos que podemos nos referir atravs de um alias. Alm disso, filtramos a consulta pela id utilizando o operador "." at chegar no atributo id da conta da movimentao. Por fim, concatenamos a id procurado na consulta. Com a query pronta obtivermos o resultado, uma lista de movimentaes, chamando o
mtodo getResultList() do objeto query criado. Com a lista podemos precorre-la de maneira tradicional atravs do um foreach.
mtodo setParameter(..) do objeto query que recebe a posio do parmetro e valor que ser recibido. Essa forma conhecido como Positional Parameter Notation. Abaixo temos um exemplo do uso:
package br.com.caelum.financas.teste;
// imports omitidos
public class TestaConsulta { public static void main(String[] args) { EntityManager manager = new JPAUtil().getEntityManager(); Conta conta = new Conta(); conta.setId(1); Query query = manager .createQuery("select m from Movimentacao m where m.conta=?1"); query.setParameter(1, conta); List<Movimentacao> movimentacoes = query.getResultList(); for (Movimentacao m : movimentacoes) { System.out.println("\nDescricao ..: " + m.getDescricao()); System.out.println("Valor ......: R$ " + m.getValor()); } } }
O problema da Positional Parameter Notation que quando temos muitos parmetros fica fcil confundir-se com os nmeros, com isso acabamos errando as posies.
List<Movimentacao> movimentacoes = query.getResultList(); for (Movimentacao m : movimentacoes) { System.out.println("\nDescricao ..: " + m.getDescricao()); System.out.println("Valor ......: R$ " + m.getValor()); } } }
Query query = manager .createQuery("select m from Movimentacao m where m.conta = :pConta " + " order by m.valor desc");
query.setParameter("pConta", conta);
Resumo
Nesta aula vimos como consultar o nosso modelo atravs de JPQL. Tambm foi apresentado a possibilidade de passar parmetros para essas consultas sendo o mais recomendado o Named Parameter Notation que utilize o nome do parmetro no lugar da posio do parmetro na query. Tudo atravs do objeto do tipo javax.persistence.Query que abre peloEntityManager. Este mesmo objeto retornou os dados da consulta atravs do mtodo getResultList().