• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Aula JPA
 

Aula JPA

on

  • 422 views

Apostila da aula de JPA, cobrindo os seguintes tópicos: ...

Apostila da aula de JPA, cobrindo os seguintes tópicos:
- jpa
- hibernate
- many-to-one
- mapeamento objeto relacional
- entity manager
- junit
- namedquery
- query

Statistics

Views

Total Views
422
Views on SlideShare
418
Embed Views
4

Actions

Likes
1
Downloads
13
Comments
0

2 Embeds 4

http://www.slideee.com 3
http://www.linkedin.com 1

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Aula JPA Aula JPA Presentation Transcript

    • Java Persistence API JPA Marco Reis Software Architect http://marcoreis.net
    • Agenda • Mapeamento objeto-relacional. • JPA x Hibernate. • Criação das tabelas. • Executar comandos de inclusão, alteração, exclusão e consulta.
    • Código-fonte • O projeto de exemplo com o código-fonte está disponível em: – https://github.com/masreis/e-commerce
    • 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.
    • 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.
    • 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.
    • 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>
    • 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.
    • Classe Usuario package 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} }
    • Classe Usuario persistente @Entity public 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.
    • Teste unitário com JUnit • 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(). <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> </dependency>
    • Inserindo registros public 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("ma@marcoreis.net"); usuario.setNome("Marco Reis"); Date data = new Date(); usuario.setUltimoLogin(data); em.persist(usuario); } }
    • Consulta registros gravados • 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. @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; }
    • NamedQuery • 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. @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; }
    • Consulta registros gravados • Em seguida, vamos criar o teste unitário para verificar os usuários cadastrados. public class TesteConsultaUsuarios { private EntityManager em; @Before public void inicializar() { em = JPAUtil.getInstance().getEntityManager(); } @After public void finalizar() { em.close(); } }
    • Consulta registros gravados • O primeiro teste unitário utiliza uma Query, retornando todos os usuários cadastrados. @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()); } }
    • Consulta registros gravados • O teste unitário abaixo acessa a NamedQuery e passa um parâmetro, mostrando apenas os registros que têm a data de hoje. @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()); } }
    • 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("diego@lucas.net"); usuario.setNome("Diego Lucas"); Date data = new Date(); usuario.setUltimoLogin(data); em.persist(usuario); }
    • 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); }
    • 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.
    • 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. @Entity public class Cliente extends Usuario { @Column(unique = true, nullable = false) private String cpfCnpj; {sets e gets} }
    • 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("jose@oracle.com"); cliente.setNome("Jose Carlos"); // cliente.setCpfCnpj("123456"); em.persist(cliente); Assert.assertTrue("Cliente gravado com sucesso", cliente.getId() > 0); }
    • 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 (?, ?)
    • Atividade • Crie as classes de teste Categoria: – Inclusão. – Alteração. – Exclusão. – Consulta todas as categorias.
    • Relacionamentos • O JPA tem as seguintes multiplicidades, seguindo o modelo relacional: – many-to-one. – one-to-one. – one-to-many. – many-to-many.
    • 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; }
    • 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); }
    • 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()); } }
    • 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()); } }
    • Consultando quantidades • Adicione as NamedQueries abaixo em Produto e o teste na classe TesteConsultaProdutos. @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") }) @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); }
    • 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).
    • Referência • http://docs.oracle.com/javaee/6/tutorial/