sexta-feira, 8 de janeiro de 2010

Aplicação de Exemplo usando Hibernate/JPA e DAOs Genéricos

Desafio DF-JUG

Este post foi escrito com o objetivo de responder ao desafio proposto pelo colega Roberto Messa no DFJUG em 07/01/2010. A solução proposta pelo Messa era baseada em JDBC puro, usando DAOs que encapsulavam comandos SQL. Seria interessante se aproveitássemos o desafio para fazer um estudo comparativo entre várias tecnologias, mostrando como cada uma delas soluciona o problema.

Persistence.xml - Configurar a conexão que será usada pela Unidade de Persistência

É o único XML da aplicação, onde configuramos o JPA.

Vantagens

  • caso a aplicação não utilize recursos específicos do BD, para trocar de SGBD basta
    • reconfigurar o dialeto,
    • o driver
    • e a URL de conexão.
  • Não é necessário recompilar a aplicação.
  • O Hibernate gera as tabelas automaticamente... (não preciso das SQL para DDL)

Interface GenericDao.java

Classe JpaDao.java

Fornece a implementação básica do Dao, que pode ser reutilizada para todos os demais. Acabou ficando um pouco extensa, pois incluí nela lógica transacional, estilo BMT (Bean Managed Transactions - soluções declarativas são mais robustas e adequadas, mas para fins didáticos, manterei BMT através do DAO).

Acrescentei no construtor algumas linhas, para o DAO saber qual o tipo genérico com o qual foi parametrizado.

Começa a brincadeira

ProdutoDao

Vazio... (apenas extende e parametriza JpaDao).

Produto.java

Um POJO.... (maior parte gerada usando a IDE - getters, setters e construtores).

Main.java

Respondendo ao desafio:

Saída

Rebatendo desafio, parte 1: Controle de Transações

Caso vc esteja realizando operações que salvam varios registros, e ocorre uma exceção no meio da operação, qual a estratégia? O que foi salvo, continua no BD e o que nao foi salvo se perde? Desfaz todas as alterações? Mesmo usando BMT, que é feio, o exemplo abaixo ilustra essa situação:

Saída

Ou seja, a aplicação chegou a salvar A2 (o ID foi gerado), mas após a exceção em A3, a aplicação fez rollback na transação de desfez todas as operações.

Rebatendo desafio, parte 2: Mais entidades

Vamos "pagar", ou "recuperar o investimento" do código extra de JpaDao na primeira iteração:

ClienteDao.java

Cód. Adicional em Main.java:

Cliente.java é só mais um POJO...

Rebatendo desafio parte 3: Relacionamentos e Cascateamento de Persistência

De uma tacada só, vou salvar um Pedido e seus Itens (OneToMany). Também há métodos adicionais, para calcular total do Pedido.

PedidoDao.java

Pedido.java

ItemPedido.java

Main.java

Em pedidoDao.save, salvo, em uma única linha, 3 objetos: o pedido, e seus dois itens.

Saída

SQL

Eu particularmente só gosto de SQL quando preciso descer no nivel do BD para analisar os dados salvos... Vejamos tudo o que o JPA/Hibernate geraram, sem que eu tenha escrito nenhum SQL em toda a aplicação...