Aula JPA
-
Upload
marco-reis -
Category
Technology
-
view
524 -
download
4
description
Transcript of Aula JPA
![Page 1: Aula JPA](https://reader035.fdocumentos.com/reader035/viewer/2022062319/55731fccd8b42aae7b8b4c1f/html5/thumbnails/1.jpg)
Java Persistence APIJPA
Marco ReisSoftware Architecthttp://marcoreis.net
![Page 2: Aula JPA](https://reader035.fdocumentos.com/reader035/viewer/2022062319/55731fccd8b42aae7b8b4c1f/html5/thumbnails/2.jpg)
Agenda• Mapeamento objeto-relacional.
• JPA x Hibernate.
• Criação das tabelas.
• Executar comandos de inclusão, alteração, exclusão e consulta.
![Page 3: Aula JPA](https://reader035.fdocumentos.com/reader035/viewer/2022062319/55731fccd8b42aae7b8b4c1f/html5/thumbnails/3.jpg)
Código-fonte• O projeto de exemplo com o código-fonte está disponível
em:
– https://github.com/masreis/e-commerce
![Page 4: Aula JPA](https://reader035.fdocumentos.com/reader035/viewer/2022062319/55731fccd8b42aae7b8b4c1f/html5/thumbnails/4.jpg)
Mapeamento objeto-relacional• JPA é um modelo de persistência baseado
em POJO.• Java é utilizada em ambientes corporativos,
com grandes bancos de dados.• Agiliza o desenvolvimento, já que não
precisamos escrever comandos SQL.• Fácil de mudar de banco de dados, caso
necessário.
![Page 5: Aula JPA](https://reader035.fdocumentos.com/reader035/viewer/2022062319/55731fccd8b42aae7b8b4c1f/html5/thumbnails/5.jpg)
JPA x Hibernate
• JPA é a especificação da Oracle para mapenamento objeto-relacional.
• Hibernate apresentava uma maneira mais elegante de trabalhar com a persistência do que o J2EE.
![Page 6: Aula JPA](https://reader035.fdocumentos.com/reader035/viewer/2022062319/55731fccd8b42aae7b8b4c1f/html5/thumbnails/6.jpg)
Arquivo de configuração• O arquivo persistence.xml contém os parâmetros de
configuração para acesso ao banco de dados e deve estar no diretório META-INF.
• Persistence unit name (e-commerce-pu): indica os parâmetros de acesso à base de dados.
• transaction-type: RESOURCE_LOCAL para servidor web e JTA para servidor de aplicação.
• Provider: qualquer implementação do JPA. Pode ser o Hibernate, OpenJPA ou EclipseLink, que é o produto oficial da Oracle.
![Page 7: Aula JPA](https://reader035.fdocumentos.com/reader035/viewer/2022062319/55731fccd8b42aae7b8b4c1f/html5/thumbnails/7.jpg)
persistence.xml<?xml version="1.0" encoding="UTF-8"?><persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="e-commerce-pu" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" /> <property name="hibernate.hbm2ddl.auto" value="update" /> <property name="hibernate.show_sql" value="true" /> <property name="hibernate.format_sql" value="true" />
<property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver" /> <property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:file:e-commerce/db;shutdown=true;hsqldb.write_delay=false;" /> <property name="javax.persistence.jdbc.user" value="SA" /> <property name="javax.persistence.jdbc.password" value="" /> </properties> </persistence-unit></persistence>
![Page 8: Aula JPA](https://reader035.fdocumentos.com/reader035/viewer/2022062319/55731fccd8b42aae7b8b4c1f/html5/thumbnails/8.jpg)
Entidades• Com JPA podemos mapear as classes de entidade
diretamente para o banco de dados.
• Vamos considerar as seguintes classes:
– Usuario
– Cliente
– Produto
– Categoria
• As anotações do JPA estão no pacote javax.persistence.
![Page 9: Aula JPA](https://reader035.fdocumentos.com/reader035/viewer/2022062319/55731fccd8b42aae7b8b4c1f/html5/thumbnails/9.jpg)
Classe Usuariopackage net.marcoreis.ecommerce.entidades;
import java.util.Date;
public class Usuario { private Long id; private String email; private String nome; private Date ultimoLogin;
{sets e gets}
}
![Page 10: Aula JPA](https://reader035.fdocumentos.com/reader035/viewer/2022062319/55731fccd8b42aae7b8b4c1f/html5/thumbnails/10.jpg)
Classe Usuario persistente@Entitypublic class Usuario { @Id @GeneratedValue private Long id; private String email; private String nome; private Date ultimoLogin;}
• Para persistir uma classe usando JPA é necessário adicionar ao menos as seguintes anotações:
– @Entity: a classe será armazenada em uma tabela.
– @Id: campo da chave-primária.
– @GeneratedValue: a chave-primária será gerada automaticamente.
![Page 11: Aula JPA](https://reader035.fdocumentos.com/reader035/viewer/2022062319/55731fccd8b42aae7b8b4c1f/html5/thumbnails/11.jpg)
Teste unitário com JUnit
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version></dependency>
• As funcionalidades serão testadas com o Junit.
• Cada funcionalidade será validada com um teste unitário.
• As classes de teste vão ficar no pacote:
– net.marcoreis.ecommerce.teste
• As classes do JUnit estão em org.junit.
• Para rodar um teste, vá no menu Run-Run as-JUnit test.
• Adicione a dependência do Maven no pom.xml.
• Utilize o @Before e @After para inicializar e finalizar variáveis. Quando o teste envolver inclusão, alteração ou exclusão de registros, é obrigatório o begin() e commit().
![Page 12: Aula JPA](https://reader035.fdocumentos.com/reader035/viewer/2022062319/55731fccd8b42aae7b8b4c1f/html5/thumbnails/12.jpg)
Inserindo registrospublic class TesteInsereUsuario {
private EntityManager em;
@Before public void inicializar() { em = JPAUtil.getInstance().getEntityManager(); em.getTransaction().begin(); }
@After public void finalizar() { em.getTransaction().commit(); em.close(); }
@Test public void inserirUsuario() { Usuario usuario = new Usuario(); usuario.setEmail("[email protected]"); usuario.setNome("Marco Reis"); Date data = new Date(); usuario.setUltimoLogin(data); em.persist(usuario); }}
![Page 13: Aula JPA](https://reader035.fdocumentos.com/reader035/viewer/2022062319/55731fccd8b42aae7b8b4c1f/html5/thumbnails/13.jpg)
Consulta registros gravados
@Entity@NamedQuery(name = "usuario.consultaAcessoDia", query = "from Usuario where cast(ultimoLogin as date) = :data")public class Usuario { @Id @GeneratedValue private Long id; private String email; private String nome; private Date ultimoLogin;}
• Para consultar os registros já gravados vamos usar uma Query ou uma NamedQuery.
• A NamedQuery fica na classe persistente, enquanto que a Query pode estar em qualquer outra classe do sistema.
• Os parâmetros podem usar as seguintes formas:– :nomeParametro1, :nomeParametro2.
– ?1, ?2, ?3.
![Page 14: Aula JPA](https://reader035.fdocumentos.com/reader035/viewer/2022062319/55731fccd8b42aae7b8b4c1f/html5/thumbnails/14.jpg)
NamedQuery
@Entity@NamedQuery(name = "usuario.consultaAcessoDia", query = "from Usuario where cast(ultimoLogin as date) = :data")public class Usuario { @Id @GeneratedValue private Long id; private String email; private String nome; private Date ultimoLogin;}
• Adicione uma NamedQuery em Usuario.
• O cast é necessário porque a data é armazenada em timestamp, e a consulta deve considerar somente a data, ignorando a hora/minuto/segundo.
![Page 15: Aula JPA](https://reader035.fdocumentos.com/reader035/viewer/2022062319/55731fccd8b42aae7b8b4c1f/html5/thumbnails/15.jpg)
Consulta registros gravados
public class TesteConsultaUsuarios {
private EntityManager em;
@Before public void inicializar() { em = JPAUtil.getInstance().getEntityManager(); }
@After public void finalizar() { em.close(); }
}
• Em seguida, vamos criar o teste unitário para verificar os usuários cadastrados.
![Page 16: Aula JPA](https://reader035.fdocumentos.com/reader035/viewer/2022062319/55731fccd8b42aae7b8b4c1f/html5/thumbnails/16.jpg)
Consulta registros gravados
@Test public void consultaTodosUsuarios() { String queryJPA = "from Usuario"; Query query = em.createQuery(queryJPA); List<Usuario> usuarios = query.getResultList(); for (Usuario usuario : usuarios) { System.out.println("Nome: " + usuario.getNome()); } }
• O primeiro teste unitário utiliza uma Query, retornando todos os usuários cadastrados.
![Page 17: Aula JPA](https://reader035.fdocumentos.com/reader035/viewer/2022062319/55731fccd8b42aae7b8b4c1f/html5/thumbnails/17.jpg)
Consulta registros gravados
@Test public void consultaUsuriosAcessoDia() { em = JPAUtil.getInstance().getEntityManager(); Query query = em.createNamedQuery("usuario.consultaAcessoDia"); query.setParameter("data", new Date()); List<Usuario> usuarios = query.getResultList(); for (Usuario usuario : usuarios) { System.out.println("Nome/ultimo login: " + usuario.getNome() + " - " + usuario.getUltimoLogin()); } }
• O teste unitário abaixo acessa a NamedQuery e passa um parâmetro, mostrando apenas os registros que têm a data de hoje.
![Page 18: Aula JPA](https://reader035.fdocumentos.com/reader035/viewer/2022062319/55731fccd8b42aae7b8b4c1f/html5/thumbnails/18.jpg)
Alterando registros gravados• Para os testes abaixo crie a classe TesteAlteraUsuario.
• Para alterar um registro, primeiro faça uma consulta pelo ID. Dessa forma, o objeto será gerenciado pelo EntityManager e poderá ser atualizado.
@Test public void alterarUsuario() { Long id = 2l; Usuario usuario = em.find(Usuario.class, id); Assert.assertNotNull("Usuario não cadastrado", usuario); usuario.setEmail("[email protected]"); usuario.setNome("Diego Lucas"); Date data = new Date(); usuario.setUltimoLogin(data); em.persist(usuario); }
![Page 19: Aula JPA](https://reader035.fdocumentos.com/reader035/viewer/2022062319/55731fccd8b42aae7b8b4c1f/html5/thumbnails/19.jpg)
Removendo registros gravados• Para os testes abaixo crie a classe
TesteRemoveUsuario.
• A exclusão deve ser feita após uma consulta pelo ID, seguindo a mesma ideia da alteração.
@Test public void removerUsuario() { Long id = 5l; Usuario usuario = em.find(Usuario.class, id); Assert.assertNotNull("Usuario não cadastrado", usuario); em.remove(usuario); }
![Page 20: Aula JPA](https://reader035.fdocumentos.com/reader035/viewer/2022062319/55731fccd8b42aae7b8b4c1f/html5/thumbnails/20.jpg)
Herança• Há 3 estratégias de herança no JPA:
– JOINED: uma tabela para cada entidade, não repete os campos.
– SINGLE_TABLE: apenas uma tabela para todas as classes.
– TABLE_PER_CLASS: uma tabela para cada classe, repetindo todos os campos.
![Page 21: Aula JPA](https://reader035.fdocumentos.com/reader035/viewer/2022062319/55731fccd8b42aae7b8b4c1f/html5/thumbnails/21.jpg)
Classe Cliente• Para mostrar o funcionamento da herança no JPA, crie a
classe Cliente, subclasse de Usuario.
• Não é necessário redefinir o Id, que já está na superclasse.@Entitypublic class Cliente extends Usuario { @Column(unique = true, nullable = false) private String cpfCnpj;
{sets e gets}}
![Page 22: Aula JPA](https://reader035.fdocumentos.com/reader035/viewer/2022062319/55731fccd8b42aae7b8b4c1f/html5/thumbnails/22.jpg)
Teste do Cliente• Agora, crie a classe TesteInsereCliente para testar a
nova entidade.
• Não se esqueça dos métodos de inicialização e finalização.
• A título de teste, comente a linha do cpfCnpj e veja o resultado.
@Test public void inserirCliente() { Cliente cliente = new Cliente(); cliente.setEmail("[email protected]"); cliente.setNome("Jose Carlos"); // cliente.setCpfCnpj("123456"); em.persist(cliente); Assert.assertTrue("Cliente gravado com sucesso", cliente.getId() > 0); }
![Page 23: Aula JPA](https://reader035.fdocumentos.com/reader035/viewer/2022062319/55731fccd8b42aae7b8b4c1f/html5/thumbnails/23.jpg)
Como funciona• Acompanhando o log do Hibernate podemos verificar
que foram incluídos 2 registros, um na tabela Usuario e outro na tabela Cliente.
• Isso porque a estratégia de herança selecionada foi JOINED.Hibernate: insert into Usuario (id, email, nome, ultimoLogin) values (default, ?, ?, ?)Hibernate: insert into Cliente (cpfCnpj, id) values (?, ?)
![Page 24: Aula JPA](https://reader035.fdocumentos.com/reader035/viewer/2022062319/55731fccd8b42aae7b8b4c1f/html5/thumbnails/24.jpg)
Atividade• Crie as classes de teste Categoria:
– Inclusão.
– Alteração.
– Exclusão.
– Consulta todas as categorias.
![Page 25: Aula JPA](https://reader035.fdocumentos.com/reader035/viewer/2022062319/55731fccd8b42aae7b8b4c1f/html5/thumbnails/25.jpg)
Relacionamentos• O JPA tem as seguintes multiplicidades, seguindo o
modelo relacional:
– many-to-one.
– one-to-one.
– one-to-many.
– many-to-many.
![Page 26: Aula JPA](https://reader035.fdocumentos.com/reader035/viewer/2022062319/55731fccd8b42aae7b8b4c1f/html5/thumbnails/26.jpg)
Many-to-one• O relacionamento many-to-one está presente na classe
produto.
• Segundo o modelo, cada produto deve ter uma categoria.public class Produto { @Id @GeneratedValue private Long id; @ManyToOne private Categoria categoria; private String nome; private String descricao; private String especificacaoLoja; @Lob private byte[] especificacaoFabricante; private Double preco;}
![Page 27: Aula JPA](https://reader035.fdocumentos.com/reader035/viewer/2022062319/55731fccd8b42aae7b8b4c1f/html5/thumbnails/27.jpg)
Inserindo produtos• Para inserir um produto precisamos escolher uma
categoria válida.
• O primeiro passo é pesquisar uma categoria já cadastrada.
• Em seguida podemos preencher os demais atributos e persistir a entidade.
@Test public void inserirProduto() { Long idCategoria = 12l; Categoria categoria = em.find(Categoria.class, idCategoria); Assert.assertNotNull("Categoria não cadastrada", categoria); Produto produto = new Produto(); produto.setCategoria(categoria); produto.setDescricao("Colcha para cama de solteiro 120cm x 210cm"); produto.setNome("Colcha para cama de solteiro"); produto.setPreco(150.00); em.persist(produto); }
![Page 28: Aula JPA](https://reader035.fdocumentos.com/reader035/viewer/2022062319/55731fccd8b42aae7b8b4c1f/html5/thumbnails/28.jpg)
Consultando produtos• Para os exemplos seguintes crie a classe
TesteConsultaProdutos.
• O primeiro teste, consultarTodasCategorias, segue o mesmo princípio das demais.
@Test public void consultarTodosProdutos() { System.out.println("Consultar todos os produtos"); List<Produto> produtos = em.createQuery("from Produto").getResultList(); for (Produto p : produtos) { System.out.println(p.getId() + " - " + p.getNome()); } }
![Page 29: Aula JPA](https://reader035.fdocumentos.com/reader035/viewer/2022062319/55731fccd8b42aae7b8b4c1f/html5/thumbnails/29.jpg)
Consultando produtos pela categoria• O exemplo abaixo mostra os produtos de uma categoria
específica.
• Este teste usa uma Query, mas poderia ser facilmente adaptado para utilizar NamedQuery.
@Test public void consultarProdutosPelaCategoria() { System.out.println("Consultar produtos pela categoria"); Long idCategoria = 12l; List<Produto> produtos = em .createQuery("from Produto where categoria.id = ?1") .setParameter(1, idCategoria ).getResultList(); for (Produto p : produtos) { System.out.println(p.getId() + " - " + p.getNome()); } }
![Page 30: Aula JPA](https://reader035.fdocumentos.com/reader035/viewer/2022062319/55731fccd8b42aae7b8b4c1f/html5/thumbnails/30.jpg)
Consultando quantidades• Adicione as NamedQueries abaixo em Produto e o teste
na classe TesteConsultaProdutos.
@Test public void consultarTotalProdutoPelaCategoria() { System.out.println("Consultar total de produtos pela categoria"); Query query = em.createNamedQuery("produto.consultaTotalPorCategoria"); Long idCategoria = 12l; query.setParameter("idCategoria", idCategoria); Object resultado = query.getSingleResult(); System.out.println("Total de produtos na categoria: " + resultado); }
@NamedQueries({ @NamedQuery(name = "produto.consultaTotalPorCategoria", query = "select count(p) from Produto p where categoria.id = :idCategoria"), @NamedQuery(name = "produto.consultaPorIntervaloPreco", query = "from Produto where preco >= ?1 and preco <= ?2") })
![Page 31: Aula JPA](https://reader035.fdocumentos.com/reader035/viewer/2022062319/55731fccd8b42aae7b8b4c1f/html5/thumbnails/31.jpg)
Atividades• Criar o teste unitário para a NamedQuery
'produto.consultaPorIntervaloPreco' na classe TesteConsultaProdutos.
• Criar as classes abaixo, com seus relacionamentos, atributos e testes unitários.
– Venda (id, data, cliente).
– Item (id, produto, quantidade, valorUnitario, venda).