Na maioria das vezes é útil utilizar componentes de listas conhecidos como Combobox ou Dropdown para mostrar relacionamentos de dados entre tabelas e de uma forma amigável exibir a descrição dos itens de dados e manipular seu identificador único. Para isto o JavaServer Faces nos disponibiliza componentes e classes no qual nos permite manipular dados através de objetos e persisti-los em um banco de dados relacional usando o Hibernate. Um relacionamento de dados mais simples é criado através de duas tabelas, sendo uma tabela pai que contem os dados mestres e uma filho que contem um ou mais identificadores relacionados ao pai. Um modo de fácil de identificar e tradicional de utilizar relacionamentos em um banco de dados é através de chaves estrangeiras, uma chave estrangeira é um campo, que aponta para a chave primária de outra tabela ou da mesma tabela. Ou seja, passa a existir uma relação entre duas tabelas ou de uma única tabela. A finalidade da chave estrangeira é garantir a integridade dos dados referenciais, pois apenas serão permitidos valores que supostamente vão aparecer na base de dados e estão ligados ao registro mestre.
Exibindo Relacionamentos
1 – Primeiro crie duas tabelas e seus respectivos objetos no banco de dados Oracle, atente-se para a chave estrangeira que cria o relacionamento entre as tabelas usando a chave primaria da tabela pai:
2 – Crie uma aplicação JSF e use o código abaixo, o código é o mesmo dos exemplos anteriores, porem criamos novos objetos e novos modelos para comportar o relacionamento de dados das duas tabelas e exibi-los de uma forma amigável na pagina web. Clicando no botão de enviar, você automaticamente grava os dados no banco de dados:
3 – Assim que os dados forem enviados o Hibernate gravará o conteúdo dos objetos no banco de dados relacional, você pode verificar na pagina que mostramos a descrição do campo cargo toda vez que utilizamos os dados da tabela de Cargos, porem na tabela Participante apenas seu identificador é gravado formando o relacionamento entre as duas tabelas:
Exemplo:
Neste exemplo criamos duas tabelas no banco de dados Oracle e as relacionamos através da chave primaria e uma chave estrangeira. Usamos um elemento JSF para tornar este relacionamento amigável, exibindo assim a descrição do relacionamento mas manipulando seu identificador e os persistindo através do Hibernate.
SQL
-- Cria Sequence Participante
CREATE SEQUENCE SEQ_PARTICIPANTE
START WITH 1
INCREMENT BY 1
NOCACHE
NOCYCLE;
-- Cria tabela de participantes
CREATE TABLE PARTICIPANTE
(
ID_PART INTEGER NOT NULL
, NOME VARCHAR2(30) NOT NULL
, SOBRENOME VARCHAR2(70) NOT NULL
, ID_CARGO INTEGER NOT NULL
, DATA_ADMISSAO DATE NOT NULL
, SALARIO NUMBER(9,2) NOT NULL
, GENERO VARCHAR2(20) NOT NULL
, ATIVO CHAR(5) NOT NULL
, OBSERVACAO VARCHAR2(255)
, CONSTRAINT PARTICIPANTE_PK PRIMARY KEY
(
ID_PART
)
ENABLE
);
-- Cria Sequence Cargo
CREATE SEQUENCE SEQ_CARGO
START WITH 1
INCREMENT BY 1
NOCACHE
NOCYCLE;
-- Cria tabela de cargo
Create Table CARGO (
ID_CARGO INTEGER NOT NULL,
DESC_CARGO VARCHAR2(50) NOT NULL,
CONSTRAINT CARGO_PK PRIMARY KEY
(
ID_CARGO
)
ENABLE
);
-- Alimenta dados na tabela de cargos
insert into cargo values (SEQ_CARGO.NEXTVAL , 'Vocalista');
insert into cargo values (SEQ_CARGO.NEXTVAL, 'Guitarrista');
insert into cargo values (SEQ_CARGO.NEXTVAL, 'Baixista');
insert into cargo values (SEQ_CARGO.NEXTVAL, 'Baterista');
-- Cria Contraint chave estrangeira
ALTER TABLE PARTICIPANTE ADD CONSTRAINT CARGO_FK
FOREIGN KEY (ID_CARGO) REFERENCES CARGO (ID_CARGO);
Java
Hibernate.cfg.xml
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521:xe</property>
<property name="hibernate.connection.username">user</property>
<property name="hibernate.connection.password">pass</property>
<property name="hibernate.connection.pool_size">10</property>
<property name="show_sql">true</property>
<property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property>
<property name="hibernate.current_session_context_class">thread</property>
<mapping class="org.desenvolvimento.aberto.Modelo.CargoModelo" />
<mapping class="org.desenvolvimento.aberto.Modelo.ParticipanteModelo" />
</session-factory>
</hibernate-configuration>
Participante
package org.desenvolvimento.aberto;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.model.SelectItem;
import org.desenvolvimento.aberto.Modelo.CargoModelo;
import org.desenvolvimento.aberto.Modelo.ParticipanteModelo;
import org.desenvolvimento.aberto.dao.ParticipanteDao;
// Define decoradores
@ManagedBean(name = "Participante")
@SessionScoped
public class Participante {
// Define atributos privados
private long id;
private String nome;
private String sobrenome;
private int cargo;
private Date data;
private double salario;
private String genero;
private boolean ativo;
private String observacao;
private List<SelectItem> cargoItem;
// Metodos Getter e Setter
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String getSobrenome() {
return sobrenome;
}
public void setSobrenome(String sobrenome) {
this.sobrenome = sobrenome;
}
public int getCargo() {
return cargo;
}
public void setCargo(int cargo) {
this.cargo = cargo;
}
public Date getData() {
return data;
}
public void setData(Date data) {
this.data = data;
}
public double getSalario() {
return salario;
}
public void setSalario(double salario) {
this.salario = salario;
}
public String getGenero() {
return genero;
}
public void setGenero(String genero) {
this.genero = genero;
}
public boolean isAtivo() {
return ativo;
}
public void setAtivo(boolean ativo) {
this.ativo = ativo;
}
public String getObservacao() {
return observacao;
}
public void setObservacao(String observacao) {
this.observacao = observacao;
}
public List<SelectItem> getCargoItem() {
// Cria objeto de modelo Faces
cargoItem = new ArrayList<SelectItem>();
// cria objeto DAO
ParticipanteDao participante = new ParticipanteDao();
List<CargoModelo> cargo = participante.listacargos();
// Alimenta Modelo
for (CargoModelo c : cargo) {
SelectItem selecao = new SelectItem(c.getId_cargo(), c.getCargo());
cargoItem.add(selecao);
}
return cargoItem;
}
// Grava Dados usando Hibernate
// Você pode criar um modelo de dados para este Managed Bean
// Optamos por usar o próprio objeto através da referencia This
public String enviarDados() {
// Cria objeto DAO
ParticipanteDao participante = new ParticipanteDao();
// cria objeto Modelo
ParticipanteModelo modelo = new ParticipanteModelo();
// Transfere dados ao objeto
modelo.setNome(this.getNome());
modelo.setSobrenome(this.getSobrenome());
modelo.setCargo(this.getCargo());
modelo.setData(this.getData());
modelo.setSalario(this.getSalario());
modelo.setGenero(this.getGenero());
modelo.setAtivo(String.valueOf(this.isAtivo()));
modelo.setObservacao(this.getObservacao());
// Você pode criar
boolean resultado = participante.insereDados(modelo);
// Verifica resultado
if (resultado) {
return "resultado.xhtml?faces-redirect=true";
} else {
return null;
}
}
}
IParticipanteDao
package org.desenvolvimento.aberto.dao;
import java.util.List;
import org.desenvolvimento.aberto.Modelo.CargoModelo;
import org.desenvolvimento.aberto.Modelo.ParticipanteModelo;
public interface IParticipanteDao {
// Define método abstrato
boolean insereDados(ParticipanteModelo participante);
public List<CargoModelo> listacargos();
}
ParticipanteDao
package org.desenvolvimento.aberto.dao;
import java.util.List;
import org.hibernate.Session;
import org.desenvolvimento.aberto.Factory.*;
import org.desenvolvimento.aberto.Modelo.ParticipanteModelo;
import org.desenvolvimento.aberto.Modelo.CargoModelo;
public class ParticipanteDao implements IParticipanteDao {
@Override
public boolean insereDados(ParticipanteModelo participante) {
// Declara variável de resultado
int resultado = 0;
// Cria sessão
Session session = DBConexaoFactory.getSessionFactory().openSession();
// Cria transação
session.beginTransaction();
// Persiste dados
resultado = (Integer) session.save(participante);
// Confirma e encerra transação
session.getTransaction().commit();
// Retorna resultado
if (resultado != 0) {
return true;
} else {
return false;
}
}
@Override
public List<CargoModelo> listacargos() {
List<CargoModelo> itens = null;
// Cria sessão
Session session = DBConexaoFactory.getSessionFactory().openSession();
// Cria transação
session.beginTransaction();
// Recupera dados
String sql = "FROM CargoModelo";
itens = session.createQuery(sql).list();
// Confirma e encerra transação
session.getTransaction().commit();
return itens;
}
}
DBConexaoFactory
package org.desenvolvimento.aberto.Factory;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class DBConexaoFactory {
private static final SessionFactory sessionFactory = buildSessionFactory();
// Constroi sessão
@SuppressWarnings("deprecation")
private static SessionFactory buildSessionFactory() {
try {
// buildSessionFactory não será utilizado em versões superiores
// Veremos outros métodos para criar um Factory
// Não é necessário incluir o "hibernate.cfg.xml" no configure()
// Incluímos somente a nível de fácil entendimento da chamada da
// configuração.
// Você pode retirar a chamada.
return new Configuration().configure("hibernate.cfg.xml")
.buildSessionFactory();
} catch (Throwable ex) {
// Em caso de erro
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
// Retorna Factory da sessão
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
// Encerra Sessão
public static void shutdown() {
getSessionFactory().close();
}
}
CargoModelo
package org.desenvolvimento.aberto.Modelo;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
@Entity
@Table(name = "CARGO")
public class CargoModelo {
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CARGO")
@SequenceGenerator(name = "SEQ_CARGO", sequenceName = "SEQ_CARGO")
@Column(name = "ID_CARGO")
private int id_cargo;
@Column(name = "DESC_CARGO")
private String cargo;
// Métodos Getter & Setter
public int getId_cargo() {
return id_cargo;
}
public void setId_cargo(int id_cargo) {
this.id_cargo = id_cargo;
}
public String getCargo() {
return cargo;
}
public void setCargo(String cargo) {
this.cargo = cargo;
}
}
ParticipanteModelo
package org.desenvolvimento.aberto.Modelo;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Entity;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
@Entity
@Table(name = "PARTICIPANTE")
public class ParticipanteModelo {
// Define atributos privados
@Id
@GeneratedValue(strategy=GenerationType.AUTO, generator="SEQ_PARTICIPANTE")
@SequenceGenerator(name="SEQ_PARTICIPANTE", sequenceName="SEQ_PARTICIPANTE")
@Column(name = "ID_PART")
private int id;
@Column(name = "NOME")
private String nome;
@Column(name = "SOBRENOME")
private String sobrenome;
@Column(name = "ID_CARGO")
private int cargo;
@Column(name = "DATA_ADMISSAO")
private Date data;
@Column(name = "SALARIO")
private double salario;
@Column(name = "GENERO")
private String genero;
@Column(name = "ATIVO")
private String ativo;
@Column(name = "OBSERVACAO")
private String observacao;
// Metodos Getter e Setter
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String getSobrenome() {
return sobrenome;
}
public void setSobrenome(String sobrenome) {
this.sobrenome = sobrenome;
}
public int getCargo() {
return cargo;
}
public void setCargo(int cargo) {
this.cargo = cargo;
}
public Date getData() {
return data;
}
public void setData(Date data) {
this.data = data;
}
public double getSalario() {
return salario;
}
public void setSalario(double salario) {
this.salario = salario;
}
public String getGenero() {
return genero;
}
public void setGenero(String genero) {
this.genero = genero;
}
public String getAtivo() {
return ativo;
}
public void setAtivo(String ativo) {
this.ativo = ativo;
}
public String getObservacao() {
return observacao;
}
public void setObservacao(String observacao) {
this.observacao = observacao;
}
}
Index.xhtml
<!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:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<f:loadBundle basename="resources.application" var="msg" />
<head>
<title><h:outputText value="#{msg.welcomeTitle}" /></title>
</head>
<h:body>
<h2>JSF - Desenvolvimento Aberto - Managed Beans -</h2>
<h3>
<h:outputText id="lnome"
value="Java Server Faces- Elementos de Formulário - Hibernate - Oracle Database" />
</h3>
<h:form>
<fieldset style="padding: 10px">
<legend style="padding: 5px">Cadastro:</legend>
<h:panelGrid columns="3" cellpadding="2px">
<h:outputText id="lnome" value="Nome:" />
<h:inputText id="tnome" value="#{Participante.nome}" size="30"
required="true" label="Nome"
requiredMessage="#{msg['requerido.nome']}">
<f:validateRegex pattern="[a-zA-Z]+" />
</h:inputText>
<h:message for="tnome" style="color:red" />
<h:outputText id="lsobrenome" value="Sobrenome:" />
<h:inputText id="tsobrenome" value="#{Participante.sobrenome}"
size="40" required="true" label="Sobrenome"
requiredMessage="#{msg['requerido.sobrenome']}">
<f:validateRegex pattern="[a-zA-Z]+" />
</h:inputText>
<h:message for="tsobrenome" style="color:red" />
<h:outputText id="lcargo" value="Cargo" />
<h:selectOneMenu id="tcargo" style="width:210px"
value="#{Participante.cargo}" required="true"
requiredMessage="#{msg['requerido.cargo']}">
<f:selectItem itemLabel=" - Selecione uma opção - " itemValue=""/>
<f:selectItems value="#{Participante.cargoItem}" />
</h:selectOneMenu>
<h:message for="tcargo" style="color:red" />
<h:outputText id="ldata" value="Data de Admissão" />
<h:inputText value="#{Participante.data}" required="true"
requiredMessage="#{msg['requerido.data']}">
<f:convertDateTime pattern="dd/mm/yyyy" />
</h:inputText>
<h:message for="tdata" style="color:red" />
<h:outputText id="lsalario" value="Salário" />
<h:inputText id="tsalario" value="#{Participante.salario}"
required="true" label="Salário"
requiredMessage="#{msg['requerido.salario']}"
validatorMessage="#{msg['validar.salario']}">
<f:convertNumber currencySymbol="$" type="currency" />
<f:validateDoubleRange minimum="788.00" maximum="9999.99" />
</h:inputText>
<h:message for="tsalario" style="color:red" />
<h:outputText id="lgenero" value="Sexo" />
<h:selectOneRadio id="tgenero" value="#{Participante.genero}"
required="true" requiredMessage="#{msg['requerido.genero']}">
<f:selectItem itemValue="Masculino" itemLabel="Masculino" />
<f:selectItem itemValue="Feminino" itemLabel="Feminino" />
</h:selectOneRadio>
<h:message for="tgenero" style="color:red" />
<h:outputText id="lativo" value="Ativo" />
<h:selectBooleanCheckbox value="#{Participante.ativo}"></h:selectBooleanCheckbox>
<br />
<h:outputText id="lobservacao" value="Observação" />
<h:inputTextarea value="#{Participante.observacao}" rows="7"
cols="40" />
</h:panelGrid>
</fieldset>
<br />
<h:commandButton id="submit" action="#{Participante.enviarDados}"
value="Enviar Dados" />
</h:form>
</h:body>
</html>
Resultado.xhtml
<!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:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<f:loadBundle basename="resources.application" var="msg" />
<head>
<title><h:outputText value="#{msg.welcomeTitle}" /></title>
</head>
<h:body>
<h2>JSF - Desenvolvimento Aberto - Managed Beans -</h2>
<h3>
<h:outputText id="lnome"
value="Java Server Faces- Elementos de Formulário - Hibernate - Oracle" />
</h3>
<h:panelGrid columns="2">
<h:outputLabel value="Nome:" />
<h:outputText value="#{Participante.nome}" />
<h:outputLabel value="Sobrenome:" />
<h:outputText value="#{Participante.sobrenome}" />
<h:outputLabel value="Cargo:" />
<h:outputText value="#{Participante.cargo}" />
<h:outputLabel value="Data de Admissão:" />
<h:outputText value="#{Participante.data}">
<f:convertDateTime pattern="dd/mm/yyyy" />
</h:outputText>
<h:outputLabel value="Salário" />
<h:outputText value="#{Participante.salario}">
<f:convertNumber currencySymbol="$" type="currency" />
</h:outputText>
<h:outputLabel value="Sexo:" />
<h:outputText value="#{Participante.genero}" />
<h:outputLabel value="Ativo:" />
<h:outputText value="#{Participante.ativo}" />
<h:outputLabel value="Observacao" />
<h:outputText value="#{Participante.observacao}" />
</h:panelGrid>
</h:body>
</html>




