Java Persistence API

Exercicio 1

Considerando a API de persistência JPA um dos grandes problemas a serem resolvidos é a questão da eficiência ao realizar as buscas no banco de dados. É muito comum que ao programar utilizando esta API o programador tenha q se preocupar com cada comando executado, pois estes comandos resultam em operações que podem se tornar custosas em uma aplicação que recebe muitas requisições.

O JPA possui uma opção muito utilizada que é o FechType. Essa opção controla quais entidades serão carregadas ao realizar uma operação de SELECT na base de dados. Considere o seguinte diagrama de entidade-relacionamento:

Neste caso você pode observar que existem duas entidades e uma possui uma relação OneToMany com a outra (pessoa-compra). 

Pense um pouco…

Ao realizar uma busca por compras, como o resultado é expressado?

SELECT * FROM compra;


output:

Se você conhece um pouco de SQL sabe que a coluna “pessoa_idpessoa” é a coluna que realiza a conexão entre as tabelas. Os números ali inseridos são as chaves primárias da tabela “pessoa”. 

A partir deste ponto, toda a teoria dos InnerJoins, selects aninhados são aplicadas para gerar resultados interessantes para a aplicação e mostrar ao usuário.

Onde o JPA ajuda?

Utilizando o JPA é possível buscar todas as pessoas e dentro delas acessar uma lista de compras feitas por elas.    O problema de fazer isso é que muitas vezes não queremos que esses dados sejam carregados, assim precisamos controlar se esses relacionamentos serão mesmo carregados ao realizar um select.  Para que isso seja realizado podemos utilizar o FechType.   

O funcionamento do FetchType

  Basicamente existem 2 tipos de “fetch”: LAZY loading, EAGER loading. No LAZY loading NÃO são carregados os relacionamentos dentro da busca principal. Já no EAGER loading, tudo será carregado.   Veja como utilizar o Lazy Loading:  

import javax.persistence.FetchType;  

  

@OneToOne(fetch=FetchType.LAZY)  

@JoinColumn(name="user_profile_id")  

private Profile getUserProfile() {  

        return userProfile;  

}  

  Para utilizar o Eager Loading basta substituir a linha para:   @OneToOne(fetch=FetchType.EAGER)  

Exemplo de output

Ao realizar uma operação de busca utilizando o EAGER loading  , por exemplo:

controlPessoa.findEntities()

  O resultado será algo como:  

Pessoa{idPessoa=1
, nome=vinicius dos santos
, login=vinicius
, [email protected]
, senha=1234
, compraList=[model.Compra[ idCompra=1 ], model.Compra[ idCompra=4 ]]} 

Pessoa{idPessoa=2
, nome=Mario da silva
, login=mario
, [email protected]
, senha=1234
, compraList=[model.Compra[ idCompra=3 ]]}

Pessoa{idPessoa=3
, nome=Gabriel garcia
, login=gabriel
, [email protected]
, senha=1234
, compraList=[model.Compra[ idCompra=2 ]]}
 
Pessoa{idPessoa=4
, nome=Isabela Ribeiro
, login=isabela
, [email protected]
, senha=1234
, compraList=[]}


Ao realizar a mesma busca utilizando o LAZY loading, o resultado será:

Pessoa{idPessoa=1
, nome=vinicius dos santos
, login=vinicius
, [email protected]
, senha=1234
, compraList={IndirectList: not instantiated}}

Pessoa{idPessoa=2
, nome=Mario da silva
, login=mario
, [email protected]
, senha=1234
, compraList={IndirectList: not instantiated}}
 
Pessoa{idPessoa=3
, nome=Gabriel garcia
, login=gabriel
, [email protected]
, senha=1234
, compraList={IndirectList: not instantiated}}

Pessoa{idPessoa=4
, nome=Isabela Ribeiro
, login=isabela
, [email protected]
, senha=1234
, compraList={IndirectList: not instantiated}}

O resultado de indirect list not instantiated representa a lista não carregada devido ao lazy loading.     Como exercício você deverá implementar as classes definidas na Figura 1 e testar a utilização do LAZY e do EAGER loading.   Acesse a resposta aqui:

Clique para ver nosso github

Exercicio 2

Regras do exercício:

– Neste exercício você deverá ler todo o enunciado e ao final entregar o código Java que supre todas os requisitos descrito.
– Você pode utilizar IDEs de programação (NetBeans, eclipse, etc…), no entanto, é fortemente recomendado que você compreenda TODOS os códigos gerados pela IDE. O risco de se acomodar é seu.
– Recomendamos que você utilize no mínimo 2 bases de dados diferentes para testar o funcionamento do JPA (MySQL e Postgres são as mais comuns).

1-  Compreendendo a lógica que deve ser implementada. 

Neste exercício você irá criar um conjunto de entidades com um relacionamento muito simples. As entidades serão: Pessoa (contendo: id, loggin, senha, email, nome); Compra (contendo: id, valor, data, observacao). 

Essa lógica representa o relacionamento que um cliente tem em qualquer loja onde ele pode realizar uma compra. Um cliente pode ter várias compras, no entanto, uma compra pode pertencer a apenas um cliente.

2- Quais bibliotecas você pode (deve) utilizar

  Para completar este exercício você deverá utilizar o JPA 2.x como especificação. Como implementação do JPA você pode escolher entre o Hibernate e o eclipselink. As bases de dados ficam a sua escolha, porém recomendamos o Postgres e o MySQL.     

3- Sugestão de passos para completar o exercício

  • Passo 1 – Faça a instalação das IDE’s, Banco de dados e configure o Java.
  • Passo 2 – Crie um projeto em sua IDE de preferência
  • Passo 3 – Adicione as bibliotecas necessárias ( JPA, Hibernate ou eclipselink, Driver do banco de dados) 
  • Passo 4 – Crie as classes de entidade
 @Entity
 @Table(name = "compra")
 public class Compra implements Serializable {
  
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     @Basic(optional = false)
     @Column(name = "id")
     private Integer id;
     @Column(name = "valor")
     private String valor;
     @Column(name = "data")
     @Temporal(TemporalType.DATE)
     private Date data;
     @Column(name = "observacao")
     private String observacao;
     @Column(name = "recebido")
     private Boolean recebido; 
  
     {{getters and setters}}
  
 }
  • Passo 5 – Crie os controladores contendo os métodos:
public class CompraJpaController{
           public void create(){}
           public void edit(){}
           public void destroy(){}
           public void findAll(){}
           public void findById(){}
 }
public class EmProvider {
   private static final String DB_PU = "AplicacaoAulaPU";
   public static final boolean DEBUG = true;
   private static final EmProvider singleton = new EmProvider();
   private EntityManagerFactory emf;
   
     private EmProvider() {}
       public static EmProvider getInstance() {
         return singleton;
     }
  
  
     public EntityManagerFactory getEntityManagerFactory() {
         if(emf == null) {
             emf = Persistence.createEntityManagerFactory(DB_PU);
         }
         if(DEBUG) {
             System.out.println("factory created on: " + new Date());
         }
         return emf;
     }
  
     public void closeEmf() {
         if(emf.isOpen() || emf != null) {
             emf.close();
         }
         emf = null;
         if(DEBUG) {
             System.out.println("EMF closed at: " + new Date());
         }
     }
 }
  
  • Passo 6 – Crie uma classe de teste contendo um simples método Main();
  • Passo 7 –  Dentro da classe Main(), faça:
public class TestandoPersistencia {
  
     public static void main(String[] args) {
  
         Pessoa p = new Pessoa();
  
         Date d = new Date();
  
         p.setNome("Isabela");
         p.setLoggin("isabela tal");
         p.setEmail("[email protected]");
         p.setSenha("teste");
  
         List<Compra> compras = new ArrayList<>();
  
         Compra c1 = new Compra();
         c1.setData(d);
         c1.setObservacao("compra impressora");
         c1.setRecebido(true);
         c1.setValor("890");
         CompraJpaController c = 
              new CompraJpaController(EmProvider
                                       .getInstance()
                                       .getEntityManagerFactory());
         c.create(c1);
         compras.add(c1);
         
         p.setCompraList(compras);
         
         PessoaJpaController j = 
              new PessoaJpaController(EmProvider
                                     .getInstance()
                                     .getEntityManagerFactory());
         j.create(p);
  
         System.out.println(j.findPessoaEntities());
     }
 }
  • Passo 8 – Teste!

Faça download do exercício resolvido no github:  

Acesse agora nosso código!

DESAFIO!


1) Agora que você já sabe como implementar essa lógica, o desafio é incrementar sua loja utilizando JPA. Agora você irá registrar os itens que foram compradas seguindo a ideia do seguinte diagrama de entidades:

2) Pesquise sobre a annotation @ElementCollection e tente implementar um modelo (talvez mais simples de item) que realize a mesma lógica apresentada no desafio 1.

Dica: Veja este vídeo.

Vinicius dos Santos

Apenas um apaixonado por Ciência da Computação e forma com que ela pode transformar vidas!

Deixe uma resposta