Segundo a Oracle:
"Enterprise JavaBeans (EJB) technology is the server-side component architecture for Java Platform, Enterprise Edition (Java EE). EJB technology enables rapid and simplified development of distributed, transactional, secure and portable applications based on Java technology."
Nessa postagem vamos criar um CRUD utilizando EJB como forma de injetar a conexão com o banco de dados. Atualmente está na versão 3.1, para ser utilizada com JEE 6. Eu já usei o EJB 3.0 com o JEE 5, e aquele era um "monstrinho" de pesado! Hoje nem chega ser perceptível o uso dele.
Bom... chega de teorias e vamos ao o que interessa, crie um projeto com o nome CrudJPA, caso não saiba como iniciar o JPA no projeto, use esse projeto como base (siga os passos até criar o persistence.xml).
Em Pacotes de código-fonte crie os pacotes: model, controle e dao. Dentro do pacote model crie uma classe java com o nome de Cliente.java:
Nosso modelo acima não tem nada de diferente, apenas as anotações do JPA que já foram faladas em postagens anteriores, antes que esqueçamos vamos mapear nossa entidade Cliente, dentro do persistence.xml, o mesmo deverá ficar assim:
Agora dentro do pacote dao crie uma classe java com o nome de ClienteDAO.java, com o seguinte código:
Agora vamos entender o que acontece no nosso ClienteDAO:
@Stateless: essa anotação define um bean de sessão sem estado, o que isso quer dizer? Que o nosso dao será criado toda vez que precisarmos dele. Caso precise que esse EJB se mantenha como um escopo de sessão mesmo, aí teria que usar @Stateful... mas não vem ao caso agora.
@PersistenceContext: este é usado para injetar o PU (persistence unit) em um EntityManager, veja que não é necessário instanciar um EntityManagerFactory. Lembre-se que esse TesteJPAPU é o mesmo que foi definido lá no meu persistence-unit do meu persistence.xml.
E quantos aos métodos, perceba nos códigos que não há mais a necessidade de abrir (usando em.getTransaction().begin()) e nem fechar (usando em.close()) a conexão com o banco de dados, ou seja, o EJB será o responsável por fazer isso (isso evita possíveis exception do tipo LazyInitializationException).
Apenas uma observação para o método gravar: veja que não tem o método alterar, isso pois o em.merge(cliente), funciona tanto para persistir um objeto como apenas para alterar, isso funciona assim: caso o JPA identifique que o objeto passado por parâmetro não está sendo gerenciado por ele, isso fará ele gravar um novo objeto, no caso aqui um novo cliente. Já quando você seleciona um cliente com um em.find(...) esse cliente está sendo gerenciado pelo JPA, e se mandar dar um em.merge(cliente) ele vai apenas alterar os dados, e não gravará um novo!
E agora vamos criar um bean dentro do pacote controle, para isso crie uma classe java com o nome de ClienteBean.java, dessa forma:
@EJB: Essa anotação serve para fazermos a injeção de dependência do nosso EJB, que neste caso é o ClienteDAO, por ele estar sendo injetado, em nenhum momento será necessário instância-lo com um new ClienteDAO();
Agora para finalizar de vez o CRUD, vamos alterar a página index.xhtml(que é criada juntamente com o projeto) e para não ter que criar outras páginas, fiz o CRUD inteiro somente na página index, mas aí é só fazer como desejar, esta deverá ficar assim:
Ao clicar no botão Selecionar o cliente será selecionado, e será renderizado um botão de remover, enfim quando selecionado um cliente, a janela fica assim:
Mas como eu falei, essa é apenas uma opção de como pode ser feito nossa visualização, use sua criatividade para deixá-la como achar melhor!
Para mais informações veja a API do Java EE 6, para ver mais sobre o EJB, selecione o pacote javax.ejb. Aqui finalizamos mais uma postagem... fiz ela bem simples, para dar mais foco ao EJB 3.1 com o JPA 2.0. :)
Em Pacotes de código-fonte crie os pacotes: model, controle e dao. Dentro do pacote model crie uma classe java com o nome de Cliente.java:
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="cliente")
public class Cliente implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="codigo")
private Long codigo;
@Column(length=100, name="nome")
private String nome;
public Long getCodigo() {
return codigo;
}
public void setCodigo(Long codigo) {
this.codigo = codigo;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
@Override
public int hashCode() {
int hash = 0;
hash += (codigo != null ? codigo.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
if (!(object instanceof Cliente)) {
return false;
}
Cliente other = (Cliente) object;
if ((this.codigo == null && other.codigo != null) || (this.codigo != null && !this.codigo.equals(other.codigo))) {
return false;
}
return true;
}
}
Nosso modelo acima não tem nada de diferente, apenas as anotações do JPA que já foram faladas em postagens anteriores, antes que esqueçamos vamos mapear nossa entidade Cliente, dentro do persistence.xml, o mesmo deverá ficar assim:
<persistence version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/persistence" xsi:schemalocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="TesteJPAPU" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>5tads</jta-data-source>
<class>model.Cliente</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="eclipselink.ddl-generation" value="create-tables" />
</properties>
</persistence-unit>
</persistence>
Agora dentro do pacote dao crie uma classe java com o nome de ClienteDAO.java, com o seguinte código:
package dao;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import model.Cliente;
/**
*
* @author andii
*/
@Stateless
public class ClienteDAO {
@PersistenceContext(unitName="TesteJPAPU")
private EntityManager em;
public boolean gravar(Cliente cliente){
boolean sucesso = false;
try {
em.merge(cliente);
sucesso = true;
} catch (Exception e) {
e.printStackTrace();
}
return sucesso;
}
public Cliente selecionar(Long codigo){
Cliente cliente = null;
try {
cliente = em.find(Cliente.class, codigo);
} catch (Exception e) {
e.printStackTrace();
}
return cliente;
}
public boolean remover(Cliente cliente){
boolean sucesso = false;
try {
cliente = em.find(Cliente.class, cliente.getCodigo());
em.remove(cliente);
sucesso = true;
} catch (Exception e) {
e.printStackTrace();
}
return sucesso;
}
public List<Cliente> listar() {
List<Cliente> clientes = null;
try {
Query query = em.createQuery("Select c from Cliente c");
clientes = query.getResultList();
} catch (Exception e) {
e.printStackTrace();
}
return clientes;
}
}
Agora vamos entender o que acontece no nosso ClienteDAO:
@Stateless: essa anotação define um bean de sessão sem estado, o que isso quer dizer? Que o nosso dao será criado toda vez que precisarmos dele. Caso precise que esse EJB se mantenha como um escopo de sessão mesmo, aí teria que usar @Stateful... mas não vem ao caso agora.
@PersistenceContext: este é usado para injetar o PU (persistence unit) em um EntityManager, veja que não é necessário instanciar um EntityManagerFactory. Lembre-se que esse TesteJPAPU é o mesmo que foi definido lá no meu persistence-unit do meu persistence.xml.
E quantos aos métodos, perceba nos códigos que não há mais a necessidade de abrir (usando em.getTransaction().begin()) e nem fechar (usando em.close()) a conexão com o banco de dados, ou seja, o EJB será o responsável por fazer isso (isso evita possíveis exception do tipo LazyInitializationException).
Apenas uma observação para o método gravar: veja que não tem o método alterar, isso pois o em.merge(cliente), funciona tanto para persistir um objeto como apenas para alterar, isso funciona assim: caso o JPA identifique que o objeto passado por parâmetro não está sendo gerenciado por ele, isso fará ele gravar um novo objeto, no caso aqui um novo cliente. Já quando você seleciona um cliente com um em.find(...) esse cliente está sendo gerenciado pelo JPA, e se mandar dar um em.merge(cliente) ele vai apenas alterar os dados, e não gravará um novo!
E agora vamos criar um bean dentro do pacote controle, para isso crie uma classe java com o nome de ClienteBean.java, dessa forma:
package controle;
import dao.ClienteDAO;
import java.io.Serializable;
import java.util.List;
import javax.ejb.EJB;
import javax.enterprise.context.SessionScoped;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.inject.Named;
import model.Cliente;
/**
*
* @author andii
*/
@Named(value = "clienteBean")
@SessionScoped
public class ClienteBean implements Serializable {
@EJB
private ClienteDAO clienteDAO;
private Cliente cliente = new Cliente();
private List<Cliente> clientes;
public void novo(){
cliente = new Cliente();
}
public void gravar() {
FacesContext context = FacesContext.getCurrentInstance();
boolean resultado = clienteDAO.gravar(cliente);
if (resultado) {
cliente = new Cliente();
context.addMessage(null, new FacesMessage("Cliente gravado com sucesso"));
} else {
context.addMessage(null, new FacesMessage("Falha ao gravar cliente!"));
}
}
public void selecionar(ActionEvent evento) {
Long codigo = (Long) evento.getComponent().getAttributes().get("codigo");
cliente = clienteDAO.selecionar(codigo);
}
public void remover() {
FacesContext context = FacesContext.getCurrentInstance();
boolean resultado = clienteDAO.remover(cliente);
if (resultado) {
cliente = new Cliente();
context.addMessage(null, new FacesMessage("Cliente removido com sucesso"));
} else {
context.addMessage(null, new FacesMessage("Falha ao remover cliente!"));
}
}
//Getters e Setters
public Cliente getCliente() {
return cliente;
}
public void setCliente(Cliente cliente) {
this.cliente = cliente;
}
public List<Cliente> getClientes() {
clientes = clienteDAO.listar();
return clientes;
}
public void setClientes(List<Cliente> clientes) {
this.clientes = clientes;
}
}
A unica diferença nesse bean é o fato do nosso ClienteDAO estar anotado com um @EJB.@EJB: Essa anotação serve para fazermos a injeção de dependência do nosso EJB, que neste caso é o ClienteDAO, por ele estar sendo injetado, em nenhum momento será necessário instância-lo com um new ClienteDAO();
Agora para finalizar de vez o CRUD, vamos alterar a página index.xhtml(que é criada juntamente com o projeto) e para não ter que criar outras páginas, fiz o CRUD inteiro somente na página index, mas aí é só fazer como desejar, esta deverá ficar assim:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:form id="dadosCliente">
<fieldset style="width: 350px">
<legend>Novo cliente</legend>
<h:commandButton value="Novo" action="#{clienteBean.novo}" />
</fieldset>
<fieldset style="width: 350px">
<legend>Dados do cliente</legend>
<h:panelGrid columns="4">
<h:outputText value="Nome" />
<h:inputText value="#{clienteBean.cliente.nome}" />
<h:commandButton value="Gravar" action="#{clienteBean.gravar}" />
<h:commandButton value="Remover" action="#{clienteBean.remover}" rendered="#{clienteBean.cliente.codigo > 0}" />
</h:panelGrid>
</fieldset>
</h:form>
<h:form>
<fieldset style="width: 350px">
<legend>Clientes</legend>
<h:dataTable value="#{clienteBean.clientes}" var="cliente" border="1">
<h:column>
<f:facet name="header"><h:outputText value="CODIGO" /></f:facet>
<h:outputText value="#{cliente.codigo}" />
</h:column>
<h:column>
<f:facet name="header"><h:outputText value="NOME" /></f:facet>
<h:outputText value="#{cliente.nome}" />
</h:column>
<h:column>
<h:commandButton value="Selecionar" actionListener="#{clienteBean.selecionar}">
<f:attribute name="codigo" value="#{cliente.codigo}" />
<f:ajax render=":dadosCliente" execute="@this" />
</h:commandButton>
</h:column>
</h:dataTable>
</fieldset>
</h:form>
</h:body>
</html>
Inicialmente essa seria a visualização da página index:Ao clicar no botão Selecionar o cliente será selecionado, e será renderizado um botão de remover, enfim quando selecionado um cliente, a janela fica assim:
Mas como eu falei, essa é apenas uma opção de como pode ser feito nossa visualização, use sua criatividade para deixá-la como achar melhor!
Para mais informações veja a API do Java EE 6, para ver mais sobre o EJB, selecione o pacote javax.ejb. Aqui finalizamos mais uma postagem... fiz ela bem simples, para dar mais foco ao EJB 3.1 com o JPA 2.0. :)





















