Tutorial JPA + Prime Faces

Embed Size (px)

Citation preview

Cadastro utilizando JSF2 + JPA2 + EJB3 + CDI + PrimeFaces 2.2Criando o Banco de Dados A figura abaixo mostra as tabelas que vo fazer parte de nossa demonstrao. O exemplo mostra a criao de um simples controle de vendas, onde temos apenas duas entidades: Clientes e Compras.

Criando o Projeto Vamos agora criar o nosso projeto web no NetBeans. Para isso vamos clicar no menu Arquivo -> Novo Projeto. Na janela que se abre vamos escolher a categoria Java Web do lado esquerdo e Aplicao Web do lado direito. Conforme imagem abaixo:

Na prxima tela devemos informar o nome do nosso projeto e o diretrio onde ser salvo. Escolha o nome que desejar para o projeto. Na tela seguinte onde devemos informar qual servidor gostaramos de usar e qual verso da JEE ser usada no nosso projeto. Para o nosso exemplo vamos escolher Apache e JEE6. Na tela seguinte, o assistente pergunta quais frameworks gostaramos de utilizar para desenvolver nosso projeto. Vamos marcar a opo Java Server Faces e em Complementos selecionar o PrimeFaces. Pronto, nosso projeto est criado. Precisamos agora fazer algumas configuraes no nosso projeto: configurar um tema para a aplicao. Escolha um tema, baixe e adicione s bibliotecas. Para que o tema funcione necessrio que adicione as linhas abaixo no arquivo web.xml:

1. 2. primefaces.THEME 3. cupertino 4.

Pronto, nosso projeto est criado e pronto para receber os componentes do Primefaces. Vamos ao prximo passo. Criando o arquivo persistence.xml Vamos agora navegar entre as especificaes que foram citadas no titulo do post. A primeira delas a JPA (Java Persistence API). Em geral, essa especificao define regras para o mapeamento objeto relacional. A implementao de referncia o eclipseLink,mas iremos usar o Hibernate. A especificao fala que devemos ter um arquivo de configurao, que seja independente da implementao usada. Esse arquivo contm todas as informaes necessrias para persistir objetos, conexo com o banco de dados, detalhes de caches, dentre outros. Esse arquivo chama-se persistence.xml. Vamos adicionar agora esse arquivo ao nosso projeto. Para isso, clique com o boto direito do mouse sobre o nome do projeto e em novo, escolha a opo outro. Na janela que abrir procure pela categoriaPersistncia do lado esquerdo e do lado direito procure por Unidade de Persistncia. Ao selecionar essas opes vai aparecer pra voc a janela da imagem abaixo:

Gerando as Entidades a partir do Banco de Dados Com nossa unidade de persistncia criada podemos criar nossas classes de entidades a partir de nossas tabelas. Desta forma nossas classes de modelo vo ser geradas pelo NetBeans e vo est perfeitamente anotadas com as anotaes da JPA. Para gerar as tabelas basta clicar com o boto direito do mouse a pasta pacotes de cdigos fontes e escolher a opo novo e depois outro Na janela que vai abrir procure pela

opo Persistncia do lado direito e do lado esquerdo procure por Classe de Entidade do Banco de Dados (Entity Classes from Database) a prxima janela mostrada na figura abaixo.

Nessa primeira janela apenas selecionamos o nosso data source (jdbc/sample) criado durante a criao de nossa unidade de persistncia. Ao selecionar nossas tabelas vo aparecer, em seguida temos apenas que selecionar de quais tabelas queremos gerar as classes de entidade. Vamos selecionar a tabela tab_compras e jogar para o lado direito. Observe que ao jogarmos a tabela tab_compras, automaticamente a tabela tab_clientes tambm jogada. Isso porque tab_compras possui um relacionamento de dependncia com a tabela tab_clientes. Em outras palavras, no existem compras sem clientes. A prxima janela mostrada na figura abaixo:

Na janela acima definimos o nome da classe para cada tabela e para qual pacote as classes geradas vo adicionadas. Observe que criamos o pacote qparadigmas.modelo. Pronto podemos finalizar e ver as classes geradas no pacote. Cliente.java1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. /* * To change this template, choose Tools | Templates * and open the template in the editor. */ package qparadigmas.modelo; import import import import import import import import import import import import import import import import java.io.Serializable; java.util.Date; java.util.List; javax.persistence.Basic; javax.persistence.CascadeType; javax.persistence.Column; javax.persistence.Entity; javax.persistence.GeneratedValue; javax.persistence.GenerationType; javax.persistence.Id; javax.persistence.NamedQueries; javax.persistence.NamedQuery; javax.persistence.OneToMany; javax.persistence.Table; javax.persistence.Temporal; javax.persistence.TemporalType;

/** * * @author Wagner */ @Entity @Table(name = "TAB_CLIENTES") @NamedQueries({ @NamedQuery(name = "Cliente.findAll", query = "SELECT c FROM Cliente c"), @NamedQuery(name = "Cliente.findById", query = "SELECT c FROM Cliente c WHERE c.id = : id"), @NamedQuery(name = "Cliente.findByNome", query = "SELECT c FROM Cliente c WHERE c.nome = :nome"), @NamedQuery(name = "Cliente.findByDataNascimento", query = "SELECT c FROM Cliente c WH ERE c.dataNascimento = :dataNascimento"), @NamedQuery(name = "Cliente.findByCpf", query = "SELECT c FROM Cliente c WHERE c.cpf = :cpf")}) public class Cliente implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue @Column(name = "ID") private Integer id; @Basic(optional = false) @Column(name = "NOME") private String nome; @Column(name = "DATA_NASCIMENTO") @Temporal(TemporalType.DATE) private Date dataNascimento; @Basic(optional = false) @Column(name = "CPF") private String cpf; @OneToMany(cascade = CascadeType.ALL, mappedBy = "cliente") private List compraList; public Cliente() { } public Cliente(Integer id) {

59. this.id = id; 60. } 61. 62. public Cliente(String nome, Date dataNascimento, String cpf) { 63. this.nome = nome; 64. this.dataNascimento = dataNascimento; 65. this.cpf = cpf; 66. } 67. 68. public Integer getId() { 69. return id; 70. } 71. 72. public void setId(Integer id) { 73. this.id = id; 74. } 75. 76. public String getNome() { 77. return nome; 78. } 79. 80. public void setNome(String nome) { 81. this.nome = nome; 82. } 83. 84. public Date getDataNascimento() { 85. return dataNascimento; 86. } 87. 88. public void setDataNascimento(Date dataNascimento) { 89. this.dataNascimento = dataNascimento; 90. } 91. 92. public String getCpf() { 93. return cpf; 94. } 95. 96. public void setCpf(String cpf) { 97. this.cpf = cpf; 98. } 99. 100. public List getCompraList() { 101. return compraList; 102. } 103. 104. public void setCompraList(List compraList) { 105. this.compraList = compraList; 106. } 107. 108. @Override 109. public int hashCode() { 110. int hash = 0; 111. hash += (id != null ? id.hashCode() : 0); 112. return hash; 113. } 114. 115. @Override 116. public boolean equals(Object object) { 117. // TODO: Warning - this method won't work in the case the id fields are not set 118. if (!(object instanceof Cliente)) { 119. return false; 120. } 121. Cliente other = (Cliente) object; 122. if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(o ther.id))) { 123. return false; 124. } 125. return true; 126. }

127. 128. 129. 130. 131. 132. 133. } 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56.

@Override public String toString() { return "qparadigmas.modelo.Cliente[id=" + id + "]"; }

Compra.javapackage qparadigmas.modelo; import import import import import import import import import import import import import import java.io.Serializable; java.util.Date; javax.persistence.Column; javax.persistence.Entity; javax.persistence.GeneratedValue; javax.persistence.GenerationType; javax.persistence.Id; javax.persistence.JoinColumn; javax.persistence.ManyToOne; javax.persistence.NamedQueries; javax.persistence.NamedQuery; javax.persistence.Table; javax.persistence.Temporal; javax.persistence.TemporalType;

/** * * @author Wagner */ @Entity @Table(name = "TAB_COMPRAS") @NamedQueries({ @NamedQuery(name = "Compra.findAll", query = "SELECT c FROM Compra c"), @NamedQuery(name = "Compra.findById", query = "SELECT c FROM Compra c WHERE c.id = :id "), @NamedQuery(name = "Compra.findByDescricao", query = "SELECT c FROM Compra c WHERE c.d escricao = :descricao"), @NamedQuery(name = "Compra.findByValor", query = "SELECT c FROM Compra c WHERE c.valor = :valor"), @NamedQuery(name = "Compra.findByDataCompra", query = "SELECT c FROM Compra c WHERE c. dataCompra = :dataCompra")}) public class Compra implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue @Column(name = "ID") private Integer id; @Column(name = "DESCRICAO") private String descricao; @Column(name = "VALOR") private Float valor; @Column(name = "DATA_COMPRA") @Temporal(TemporalType.DATE) private Date dataCompra; @JoinColumn(name = "CLIENTE_ID", referencedColumnName = "ID") @ManyToOne(optional = false) private Cliente cliente; public Compra() { } public Compra(Integer id) { this.id = id; } public Integer getId() { return id; }

57. 58. public void setId(Integer id) { 59. this.id = id; 60. } 61. 62. public String getDescricao() { 63. return descricao; 64. } 65. 66. public void setDescricao(String descricao) { 67. this.descricao = descricao; 68. } 69. 70. public Float getValor() { 71. return valor; 72. } 73. 74. public void setValor(Float valor) { 75. this.valor = valor; 76. } 77. 78. public Date getDataCompra() { 79. return dataCompra; 80. } 81. 82. public void setDataCompra(Date dataCompra) { 83. this.dataCompra = dataCompra; 84. } 85. 86. public Cliente getCliente() { 87. return cliente; 88. } 89. 90. public void setCliente(Cliente cliente) { 91. this.cliente = cliente; 92. } 93. 94. @Override 95. public int hashCode() { 96. int hash = 0; 97. hash += (id != null ? id.hashCode() : 0); 98. return hash; 99. } 100. 101. @Override 102. public boolean equals(Object object) { 103. // TODO: Warning - this method won't work in the case the id fields are not set 104. if (!(object instanceof Compra)) { 105. return false; 106. } 107. Compra other = (Compra) object; 108. if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(o ther.id))) { 109. return false; 110. } 111. return true; 112. } 113. 114. @Override 115. public String toString() { 116. return "qparadigmas.modelo.Compra[id=" + id + "]"; 117. } 118. 119. }

Criando os Sessions Beans

Vamos criar agora as classes que so responsveis por prover os servios de acesso ao dado. Essa classe comumente chamada de DAO (Data Acces Object). Aqui neste post vamos utilizar EJB para nossas classes de servios. A verso 3.0 dos EJBs trouxeram grandes facilidades no uso de Session Beans ao adotar anotaes, injeo de dependncias e inverso de controle. Para esse exemplo vamos criar Stateless Session Beans. Sero classes cujos objetos vo ser injetados por Injeo de Dependencia utilizando CDI (Context Dependency Injection). Um Stateless Session Beans no mantei estado de conversao com o servidor, isso significa que o tempo de vida de um objeto dura at o execuo de uma solicitao. Para criar nosso Session Bean, basta anotarmos a classe com a anotao @Stateless. Abaixo segue os cdigo das classesClienteService e ComprasService.1. @Stateless 2. public class ClienteService { 3. 4. @PersistenceContext(name = "qparadigmasPU") 5. private EntityManager entityManager; 6. 7. public List findAll() { 8. Query query = entityManager.createNamedQuery("Cliente.findAll"); 9. return query.getResultList(); 10. } 11. 12. public void save(Cliente cliente) { 13. entityManager.persist(cliente); 14. } 15. 16. public void delete(Cliente cliente) { 17. entityManager.remove(cliente); 18. } 19. 20. public void update(Cliente cliente) { 21. entityManager.merge(cliente); 22. } 23. } 24. @Stateless 25. public class ComprasService { 26. @PersistenceContext(name = "qparadigmasPU") 27. private EntityManager entityManager; 28. 29. public Collection findAll() { 30. Query query = entityManager.createNamedQuery("Compra.findAll"); 31. return query.getResultList(); 32. } 33. 34. public void save(Compra compra) { 35. entityManager.persist(compra); 36. } 37. 38. public void delete(Compra compra) { 39. entityManager.remove(compra); 40. } 41. 42. public void update(Compra compra) { 43. entityManager.merge(compra); 44. } 45. }

Criando os Controllers Controladores so classes que normalmente representam uma pgina JSF, so comumente chamadas deBackBeans ou ManagedBeans. A quem diga que so coisas diferentes, mas no existe uma explicao 100% aceita. Aqui vamos chamar de Managed Beans. Essas classes fornecem servios que visveis em nossas pginas, esses servios podem

ser mtodos, atributos ou objetos. Segundo os especialistas, o ideal que se tenha uma classe ManagedBean para cada pgina. Em nosso exemplo vamos ter apenas uma pgina, ento vamos ter um nico controlador. Vamos chamar nossa classe de VendasController. Uma observao importante que ao invs de usarmos a anotao @ManagedBean, vamos utilizar a anotao @Named, j que desejamos implementar o exemplo usando os recursos da CDI, para criar nosso controller. Quando usamos CDI necessrio criamos o arquivo beans.xml dentro da pasta WEB-INF. Isso pode ser feito facilmente clicando a pasta com o boto direito e escolhendo Novo Outro e na janela que vai abrir procure pela categoria Context Depedency Injection (CDI), em seguida do lado direito procure por beans.xml (CDI Configuration File). Quando avanar para a prxima tela, apenas digite beans para o nome do arquivo. Abaixo segue o cdigo da classe VendasController.1. @Named(value = "vendasController") 2. public class VendasController { 3. 4. @Inject 5. private ClienteService clienteService; 6. private Cliente cliente = new Cliente(); 7. 8. public VendasController() { 9. } 10. 11. public List getListaClientes() { 12. return clienteService.findAll(); 13. } 14. 15. public Cliente getCliente() { 16. return cliente; 17. } 18. 19. public void setCliente(Cliente cliente) { 20. this.cliente = cliente; 21. } 22. }

Criando a pagina JSF Para terminar essa primeira parte do post, vamos editar nossa pgina index.xhtml e vamos deixa-lo pronto para os posts seguintes. Nesse primeiro momento nossa pgina apenas vai possuir a funcionalidade de listar os clientes j cadastrados.1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19.

20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40.

A imagem abaixo mostra uma prvida pgina:

A segunda funcionalidade que vamos adicionar ser o cadastro de clientes. Vamos utilizar o mesmo controller do post anterior: VendasController. Apenas vamos fazer duas alteraes, acrescentar o mtodo adicionarCliente e colocar nosso controller no escopo de sesso. As alteraes so mostradas no cdigo abaixo: Controller no escopo de sesso: @Named @SessionScoped public class VendasController implements Serializable Mtodo adicionarCliente() public void adicionarCliente() { clienteService.save(cliente); if (cliente.getId() > 0) { FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Novo Cliente Adicionado com Sucesso!")); } else { FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Ocorreu um erro na tentativa de salvar um novo Cliente!"));

} } O cdigo acima pode ser colocado em qualquer lugar de seu Controller. Como voc pode observar, logo depois da chamada para o mtodo save, feita uma verificao para sabermos se o novo objeto foi salvo com sucesso ou se ocorreu algum erro durante a gravao. Se a gravao ocorreu com sucesso, o atributo id atualizado com o valor que foi gerado no banco pela sequencia. Caso contrrio o id continua com o valor zero. O que ns fazemos enviar uma mensagem para o usurio notificado o que aconteceu. Essa mensagem vai ser exibda em um componente p:growl que foi inserido pgina index.xhtml no post anterior. Criando a Pgina Adicionar Cliente Vamos agora criar a pgina que vai representar o cadastro de um novo cliente em nosso sistema. O cdigo da pgina que vamos fazer agora, poderia ficar na pgina index.xhtml. Mas por questo de organizao e de melhor legibilidade do cdigo vamos coloca-lo em uma pgina separada. Em seguida atravs da diretiva ui:include vamos adiciona-la nossa pagina index.xhtml. Abaixo vamos mostrar trs cdigos: O cdigo da pgina adicionar_cliente.xhtml, o cdigo de incluso da pgina de cadastro na pgina index.xhtml e o cdigo do boto Adicionar Cliente para o dialogo de cadastro. Cdigo da Pgina adicionar_cliente.xhtml

Fazendo a incluso na Pgina index.xhtml A incluso pode ser feita em qualquer parte de sua pgina. Mas o melhor lugar para se fazer logo depois que iniciar a tag . Cdigo do boto Adicionar Cliente Deixamos um boto rotulado de Adicionar Cliente na pgina index.xhtml. Vamos agora fazer que ele abra nosso dialog de cadastro de cliente quando clicado. Abaixo segue o cdigo do boto: A figura abaixo mostra nosso dialog de Cadastrado incluindo um novo cliente e atualizando nossa tabela de listagem:

A imagem abaixo mostra a tabela depois de alguns registros adicionados:

Vamos agora implementar a funcionalidade de excluso. O nosso boto de excluir j aparece na listagem porem ainda no faz nada. Vamos fazer com que ele, quando clicado, exclua um cliente de nossa base de dados. Para isso, vamos fazer duas simples alteraes: Uma na classe VendasController para adicionar o mtodo excluirCliente e adicionar um atributo, clienteSelecionado, que represente o objeto que dever ser excludo. a Segunda alterao ser na pgina index.xhtml, para adicionarmos a funcionalidade ao boto de excluir. Atributo private Cliente clienteSelecionado; //gerar getters e setters Mtodo excluirCliente() public void excluirCliente() { try { clienteService.delete(clienteSelecionado); FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Ocorreu um erro na tentativa de excluir o Cliente!")); } catch (Exception e) { FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Ocorreu um erro na tentativa de excluir o Cliente!")); } } Alterao da Pgina index.xhtml Esse cdigo vai para o boto da lixeira, que fica dentro da listagem de clientes.