Post on 10-Nov-2018
JavaServer Faces – JSF
Fernando Freitas CostaBacharel em Sistemas de Informação
Especialista em Gestão e Docência Universitária
blog.fimes.edu.br/fernandonando@fimes.edu.br
Connection
Para trabalhar com Banco de Dados (MySQL) em JSF, é necessário primeiramente ter um objeto connection, que pode ser obtido com a sintaxe a seguir:
Connection conn = DriverManager.getConnection(“jdbc:mysql://url:porta/nomeBanco”, “usuario”, “senha”);
Statement Depois de obter o objeto connection, é necessário criar um
objeto da interface java.sql.Statement, que permitirá o envio dos comandos SQL ao banco de dados.Statement stmt = conn.createStatement();
A interface java.sql.Statement possui entre outros, os métodos:◦ executeUpdate – envia comandos SQL que atualizam o banco de
dados. Retorna um inteiro com o número de registros afetados. Ex:int x = stmt.executeUpdate(“insert into usuario (id, nome, senha) values(1, ‘paulo’, ‘123’)”);
◦ executeQuery – envia comandos SQL que consultam o banco de dados. Retorna um ResultSet. Ex:
ResultSet rs = stmt.executeQuery(“select * from usuario”);
ResultSet
Um ResultSet é como uma tabela de dados que representa um
conjunto de registros obtidos de um banco de dados, geralmente pela
execução de consultas em um objeto statement.
A interface java.sql.ResultSet possui alguns métodos de navegação entre os registros obtidos:
◦ first() - posiciona o cursor no primeiro registro do objeto ResultSet.
◦ last() - posiciona o cursor no último registro do objeto ResultSet.
◦ next() -posiciona o cursor no próximo registro do objeto ResultSet. Retorna false se não houver próximo.
◦ previous() - posiciona o cursor no registro anterior do objeto ResultSet.
◦ etc...
ResultSet
Para obter os dados de um registro, devemos chamar um dos seguintes métodos da interface java.sql.ResultSet:
◦ getString() – Obtém informações do tipo String;
◦ getInt() – Obtém informações do tipo Inteiro;
◦ getDouble() – Obtém informações do tipo double
◦ E assim sucessivamente de acordo com o tipo de dado a ser obtido.
Exemplo:
while(rs.next()){
Integer id = rs.getInt(“id”);
String nome = rs.getString(“nome”);
String senha = rs.getString(“senha”);
}
Fechando Conexões Após terminar o acesso ao banco de dados, é sempre bom fechar a conexão.
Para garantir que ela seja fechada em qualquer situação, mesmo em caso de exceções, coloque o método close() dentro de um bloco try/catch/finally.
Uma boa prática neste ponto, é criar blocos try separados para tratar a conexão e para tratar as demais exceções. Ex:
try{Connection conn = DriverManager.getConnection(“jdbc:mysql://url:porta/nomeBanco”, “usuario”, “senha”);try{
Statement stmt = conn.createStatement();int x = stmt.executeUpdate(“insert into usuario (id, nome, senha) values(1, ‘paulo’, ‘123’)”);
}finally{conn.close();
}}catch(SQLException e){
...}
Outra opção melhor ainda, é definir seu método para lançar SQLException e deixar que o chamador trate estas exceções.
PreparedStatement Quando a aplicação precisa emitir várias vezes o mesmo comando SQL apenas
com valores diferentes, uma opção mais rápida para trabalhar com o banco de dados é fazer uso da interface java.sql.PreparedStatement.
Um objeto PreparedStatement solicita ao banco que uma query seja pré-compilada. Feito isto, ela é mantida e reutilizada sempre que ela for submetida novamente.
Outra boa razão para trabalhar com esta interface é evitar que entradas de usuário se transformem em SQL Injection (ataque a uma aplicação via código SQL).
O primeiro passo é criar um objeto da interface java.sql.PreparedStatement, que permitirá o envio dos comandos SQL ao banco de dados.
PreparedStatement pstmt = conn.preparedStatement(“instrução sql com parâmetros”);
PreparedStatement Para aceitar valores diferentes o objeto PreparedStatement trabalha com o
uso de parâmetros (representados pelo ponto de interrogação), que são definidos no momento da execução. Ex:
PreparedStatement pstmt = conn.preparedStatement(“select * from usuario where nome like ?”);
pstmt.setString(1, ‘fernando’);
ResultSet rs = pstmt.executeQuery();
Para definir os valores de cada parâmetro a interface java.sql.PreparedStatement fornece os métodos:
◦ setString() – Define parâmetros do tipo String;
◦ setInt() – Define parâmetros do tipo Integer/int.
◦ setDouble() – Define parâmetros do tipo Double/double.
◦ E assim sucessivamente, de acordo com o tipo do parâmetro a ser definido.
◦ Estes métodos recebem dois parâmetros:
O primeiro é um número referente a qual ponto de interrogação você está se referindo (1º, 2º, 3º, ...).
O segundo é o valor que deve ser atribuído ao parâmetro.
PreparedStatement Assim como a interface java.sql.Statement, a interface
java.sql.PreparedStatement também possui entre outros, os métodos:
◦ executeUpdate – envia comandos SQL que atualizam o banco de dados. Retorna um inteiro com o número de registros afetados. Ex:
PreparedStatement pstmt = conn.preparedStatement(“insert into usuario (id, nome, senha) values(?, ?, ?)”);
pstmt.setInt(1, 1);
pstmt.setString(2, ‘fernando’);
pstmt.setString(3, ’123’);
Integer resultado = pstmt.executeUpdate();
◦ executeQuery – envia comandos SQL que consultam o banco de dados. Retorna um ResultSet. Ex:
PreparedStatement pstmt = conn.preparedStatement(“select * from usuario where nome like ?”);
pstmt.setString(1, ‘fernando’);
ResultSet rs = pstmt.executeQuery();
Transações
Ao trabalhar com banco de dados, pode ser necessário utilizar o conceito de transações para confirmar ou reverter uma ou mais comandos SQL.
O uso de transações é bom por duas razões: integridade e acesso concorrente.
Por padrão, uma conexão com o banco trabalha no modo autocommit, ou seja, confirma cada comando separadamente. Portanto, ao trabalhar com transações, o primeiro passo é desativar este padrão. Ex:
conn.setAutoCommit(false);
Transações
Se durante a transação tudo correr bem, deve-se efetuar um commitao final do processo. Ex:
conn.commit();
Caso contrário, deve-se efetuar um rollback na transação. Ex:
conn.rollback ();
O exemplo a seguir mostra como lidar com transações:conn.setAutoCommit(false);boolean commited = false;try{
//operações no banco de dadosconn.commit();commited = true;
}finally{if (!commited) conn.rollback();
}
JSF e Banco de Dados
Crie um novo Dinamic Web Project com o nome ExemploBD01;
Em seguida, devemos fazer estes 6 passos.◦ Criação do banco de dados;
◦ Criação das tabelas;
◦ Criação da classe DAO;
◦ Criação da classe Bean;
◦ Mapeamento da classe Bean;
◦ Criação da página JSF.
Passos 1 e 2 – Criação do Banco e da tabela
create database jsf_bd;
use jsf_bd;
create table usuario(
id integer not null auto_increment,
nome varchar(50) not null,
email varchar(50),
fone varchar(13) not null,
primary key (id)
) engine = InnoDB;
Passo 3 – Criação da classe Bean Crie o pacote bean.
Crie uma classe chamada UsuarioBean. Ela será o meio termo entre o dao e a página JSF.
package bean;
import javax.faces.bean.ManagedBean;import dao.UsuarioDAO;
@ManagedBeanpublic class UsuarioBean {
private Integer id;private String nome, fone, email;
public Integer getId() { return id; }public void setId(Integer id) { this.id = id; }public String getNome() { return nome; }public void setNome(String nome) { this.nome = nome; }public String getFone() { return fone; }public void setFone(String fone) { this.fone = fone; }public String getEmail() { return email; }public void setEmail(String email) { this.email = email; }
public String salvar(){UsuarioDAO uDao = new UsuarioDAO();int resultado = uDao.salvar(this);if(resultado > 0){
this.nome = "";this.fone = "";this.email = "";
}return null;
}}
Passo 4 – Criação da classe DAO Crie um pacote dao
Crie uma classe chamada UsuarioDAO. Ela será responsável por lidar diretamente com o BD. Vejamos um exemplo simples:
package dao;
import java.sql.Connection;import java.sql.DriverManager;import java.sql.SQLException;import java.sql.Statement;import javax.faces.application.FacesMessage;import javax.faces.context.FacesContext;import bean.UsuarioBean;
public class UsuarioDAO {public int salvar(UsuarioBean ub) {
int resultado = 0;FacesContext ctx = FacesContext.getCurrentInstance();try {
Class.forName("com.mysql.jdbc.Driver");Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jsf_bd", "root", "vertrigo");try {
Statement stmt = conn.createStatement();resultado = stmt.executeUpdate("insert into usuario (nome, email, fone) values ('"+ ub.getNome()+ "', '"+
ub.getEmail()+ "', '" + ub.getFone() + "')");ctx.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,"Cadastro realizado com sucesso", "O
cadastro foi realizado com sucesso"));} finally { conn.close(); }
} catch (ClassNotFoundException cnfex) {ctx.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erro: Classe não encontrada", "A classe
com.mysql.jdbc.Driver não foi encontrada. Detalhe: "+ cnfex.getMessage()));} catch (SQLException sqlex) {
ctx.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Ocorreu um erro ao salvar" , "Ocorreu um erro ao executar a instrução SQL. Detalhe: "+ sqlex.getMessage()));
}return resultado;
}}
Passo 5 – Criação das páginas JSF Crie uma nova página chamada index.xhtml
<?xml version="1.0" encoding="ISO-8859-1" ?><!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"><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /><title>Insert title here</title></head><body><h:form><h:messages errorStyle="color:red" infoStyle="color:green" showDetail="true"/><h:panelGrid columns="3"><h:outputLabel value="Nome:" for="nome"/><h:inputText id="nome" value="#{usuarioBean.nome}" required="true" requiredMessage="Informe o nome"/><h:message for="nome"/>
<h:outputLabel value="E-mail:" for="email"/><h:inputText id="email" value="#{usuarioBean.email}"/><h:message for="email"/>
<h:outputLabel value="Fone:" for="fone"/><h:inputText id="fone" value="#{usuarioBean.fone}" required="true" requiredMessage="Informe o telefone"/><h:message for="fone"/>
<h:commandButton action="#{usuarioBean.salvar()}" value="Salvar" /></h:panelGrid></h:form></body></html>
Por quê não funcionou?
Não funcionou porque o Tomcat precisa que a classe com.mysql.jdbc.Driver seja informada.
Para isto, você vai precisar do Conector MySQL que pode ser obtido no endereço: http://dev.mysql.com/downloads/connector/j/
Após baixá-lo, descompacte-o e copie o arquivo mysql-connector-java-5.x.xx-bin.jar (onde o x refere-se as subversões do conector MySQL), para dentro da pasta WebContent/WEB-INF/lib
Pronto, agora sim, execute o arquivo.
Exercícios1. Com base no conteúdo passado, faça uma cópia deste
projeto e salve com o nome ExemploBD02. No projeto ExemploBD02, faça as alterações para que ele fique mais seguro, ou seja, utilize PreparedStatementno lugar das Statement utilizada.
2. Em seguida, crie uma página sucesso.xhtml que:• Deverá ser exibida em caso de sucesso ao cadastrar.
• Deve exibir os dados recém cadastrados. (Atenção, estes dados devem serconsultados no banco)
• Coloque nela um botão Voltar.