Os templates são como uma "casca" que usaremos em nosso site, aplicando em todas as telas do nosso sistema, dessa forma, alterando apenas o template, alteramos a página toda de uma só vez.
Crie um novo XHTML com o nome template para isso, de forma que tenha mais um atributo xmlns, 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://xmlns.jcp.org/jsf/html" xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<h:head>
<title>Sistema Carros</title>
</h:head>
<h:body>
</h:body>
</html>
E coloque essa estrutura nele:
<h1>Sistema Carros</h1>
<hr/>
<ui:insert name="corpo">
</ui:insert>
E no index, podemos suprimir o head e o body, chamando ele apenas com o atributo template dentro de tags decorate, 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">
<ui:decorate xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:p="http://primefaces.org/ui" xmlns:f="http://xmlns.jcp.cor/jsf/core" xmlns:ui="http://xmlns.jcp.org/jsf/facelets" template="templates.xhtml">
</ui:decorate>
Dessa forma, ele usará apenas o XML para as páginas, nada de HTML, mas para aparecer conteúdo, devemos colocar mais elementos na página index, no caso, o define, com o mesmo name do insert do template, dessa forma:
<ui:define name="corpo">
<h1>Bem-vindo ao Sistema</h1>
</ui:define>
Podemos ter mais de um insert no template, desde que tenham nomes diferentes.
Mas também podemos usar insert sem names no template, e usar um span no index, sem as tags define, assim:
<h1>Bem-vindo ao Sistema</h1>
<span>Sistema</span>
No template, podemos criar um menu assim (abaixo do h1 com Sistema Carros):
<h:form>
<p:menubar>
<p:menuitem value="Home" url="index.jsf"></p:menuitem>
<p:menuitem value="Gerenciar" url="gerenciar-carros.jsf"></p:menuitem>
</p:menubar>
</h:form>
Todas as páginas aplicadas, terão os elemento aplicados nas páginas jsf, para aplicar em todas, basta usar as tags ui:decorate.
Para adicionar o banco de dados ao nosso projeto, vá em bibliotecas e adicione a biblioteca do Driver de MySQL (ou do banco que será usado, como o PostgreSQL). O do PostgreSQL pode ser baixado daqui: https://jdbc.postgresql.org/download/
No SQL, crie o banco e a tabela com esses comandos:
create database sistema_carros
default character set utf8
default collate utf8_general_ci;
use sistema_carros;
create table carro (
id int not null auto_increment,
modelo varchar(50) not null,
fabricante varchar(20) not null,
cor varchar(20) not null,
ano date,
primary key(id)
)
default charset = utf8;
Vamos voltar ao nosso projeto de carros, com o mesmo formulário anterior.
Crie uma nova classe (num novo pacote denominado util), chamada FabricaConexao, com esse código:
package util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
public class FabricaConexao {
private static Connection conexao; // Importe
private static final String URL_CONEXAO = "jdbc:mysql://localhost:3306/sistema_carros"; // Se for postgre é jdbc:postgresql://localhost:5432/sistema_carros
private static final String USUARIO = "root";
private static final String SENHA = "";
public static Connection getConexao() {
if(conexao == null) {
try {
Class.forName("com.mysql.jdbc.Driver"); // Se for Postgre, coloque org.postgresql.Driver
conexao = DriverManager.getConnection(URL_CONEXAO, USUARIO, SENHA); // Importe
}
catch(SQLException | ClassNotFoundException ex) { // Importe
Logger.getLogger(FabricaConexao.class.getName()).log(Level.SEVERE, null, ex);
}
}
return conexao;
}
public static void fecharConexao() {
if(conexao != null) {
try {
conexao.close();
conexao = null;
}
catch(SQLException ex) {
Logger.getLogger(FabricaConexao.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
E crie um pacote com o nome DAO e uma classe com o nome CarroDAO, dessa forma:
package dao;
import classes.Carro;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Calendar;
import java.util.logging.Level;
import java.util.logging.Logger;
import util.FabricaConexao;
public class CarroDAO {
private Connection conexao = null;
public CarroDAO() {
conexao = FabricaConexao.getConexao();
}
public void salvar(Carro car) {
String sql = "insert into carro (modelo, fabricante, cor, ano) values (?, ?, ?, ?)";
try {
PreparedStatement ps = conexao.prepareStatement(sql);
Calendar ano = Calendar.getInstance(); // Importar
ano.set(Integer.parseInt(car.getAno()), 0, 1);
ps.setString(1, car.getModelo());
ps.setString(2, car.getFabricante());
ps.setString(3, car.getCor());
ps.setDate(4, new Date(ano.getTimeInMillis())); // Importe Java.sql.Date
ps.execute();
FabricaConexao.fecharConexao();
}
catch(SQLException ex) {
Logger.getLogger(CarroDAO.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
PS: Note que não precisamos usar new para criar o objeto conexao, por causa do static na outra classe. Não é necessário recebermos um retorno, por isso usamos o execute() ao invés do executeQuery(), nesse caso.
Volte na classe CarroBean e adicione a chamada da classe CarroDAO, assim:
public void adicionar() {
carros.add(car);
new CarroDAO().salvar(car); // Importe
car = new Carro();
}
Dessa forma, tudo que colocarmos no nosso formulário já será salvo, sem precisar alterar o XHTML.
Primeiramente, vamos em Carro e adicione os métodos equals e hashcode, clicando com o botão direito.
Depois, volte em CarroDAO e coloque esse método:
public List<Carro> buscar() { // Importe
String sql = "select * from carro";
try {
PreparedStatement ps = conexao.prepareStatement(sql);
ResultSet results = ps.executeQuery(); // Importe
List<Carro> carros = new ArrayList<>(); // Importe
while(results.next()) {
Carro car = new Carro();
Calendar ano = Calendar.getInstance();
ano.setTime(results.getDate("ano"));
car.setId(results.getInt("id")); // Isso pega o valor da coluna id da tabela.
car.setModelo(results.getString("modelo"));
car.setFabricante(results.getString("fabricante"));
car.setCor(results.getString("cor"));
car.setAno(String.valueOf(ano.get(Calendar.YEAR)));
carros.add(car);
}
return carros;
}
catch(SQLException ex) {
Logger.getLogger(CarroDAO.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
}
E na Carro Bean, adicione o método listar e faça algumas alterações:
private Carro car = new Carro();
private List<Carro> carros = new ArrayList<>();
private CarroDAO carD = new CarroDAO(); // Colocamos o objeto fora dos métodos pra não ter que criarmos ele toda hora
public void adicionar() {
carros.add(car);
carD.salvar(car);
car = new Carro();
}
public void listar() {
carros = carD.buscar();
}
E no xhtml, coloque esse botão, ao lado do adicionar:
<p:commandButton value="Buscar" action="#{carroBean.listar()}" update="@form"></p:commandButton>
Volte em CarroBean e coloque esse método:
public void editar(Carro c) {
car = c;
}
E no XHTML, dentro da tag dataTable, como o primeiro elemento dele, essas tags:
<p:column>
<p:commandButton value="Editar" action="#{carroBean.editar(carroForm)}" update="@form"></p:commandButton>
</p:column>
E no CarroDAO, altere o método salvar dessa forma:
public void salvar(Carro car) {
String sql;
try {
PreparedStatement ps;
if(car.getId() == null) {
sql = "insert into carro (modelo, fabricante, cor, ano) values (?, ?, ?, ?)";
ps = conexao.prepareStatement(sql);
}
else {
sql = "update carro set modelo = ?, fabricante = ?, cor = ?, ano = ? where id = ?";
ps = conexao.prepareStatement(sql);
ps.setInt(5, car.getId());
}
Calendar ano = Calendar.getInstance(); // Importar
ano.set(Integer.parseInt(car.getAno()), 0, 1);
ps.setString(1, car.getModelo());
ps.setString(2, car.getFabricante());
ps.setString(3, car.getCor());
ps.setDate(4, new Date(ano.getTimeInMillis())); // Importe Java.sql.Date
ps.execute();
FabricaConexao.fecharConexao();
}
catch(SQLException ex) {
Logger.getLogger(CarroDAO.class.getName()).log(Level.SEVERE, null, ex);
}
}
Em CarroBean, exclua o método carros.add(car)
em adicionar, para não causar confusão na visualização, já que este não interfere no banco do nosso site.
Podemos mudar também o value do button Adicionar para Adicionar/Atualizar.