Parte 1Parte 2Parte 3Parte 4.1Parte 4.2

Olá, hoje vamos continuar nosso tutorial. Inicialmente eu tinha planejado quatro partes para este tutorial, mas hoje de manhã estive pensando melhor e decidi quebrar a quarta parte em duas partes. Então teremos a parte 4.1 (esta que você está lendo) onde iremos preparar o nosso backend para fazermos um CRUD de três entidades (Estado, Cidade e Cliente). Na parte final, a 4.2, iremos tratar o lado do cliente, ou seja, a parte em Flex onde iremos montar a interface gráfica do nosso CRUD. Sendo assim, vamos começar!

Para o nosso CRUD nós não iremos usar nenhum framework, pois como eu já disse, o foco do tutorial não é esse. Se você quiser posteriormente inserir o Hibernate por exemplo, tenho certeza que não vai ter dificuldades, porque o lado do Flex não vai precisar ser modificado e o lado implementado em Java também poderá ser modificado facilmente. Para o nosso “minisistema”, vamos considerar o seguinte “documento de requisitos”:

“Desenvolver uma aplicação Web utilizando Flex e Java que permita o cadastro e a manutenção de Estados (unidades da federação), Cidades e Clientes. Um Estado é composto por um identificador (utilizado internamente no sistema), um nome e uma sigla que deve ser única. O nome de um estado não deve ter mais que 50 caracteres, enquanto a sigla deve ter obrigatoriamente 2 caracteres. Uma Cidade é composta também por um identificador, um nome (máximo 50 caracteres) e um estado. Por fim, cada Cliente é composto por um identificador, um nome (máximo 50 caracteres), um sobrenome (máximo 50 caracteres), uma data de nascimento, um CPF que deve ser único (14 caracteres) e o endereço deste Cliente deve conter uma rua (máximo 60 caracteres), um número (máximo 8 cacacteres), um CEP (9 caracteres) e uma cidade. Todos os atributos de Estado, Cidade e Cliente são obrigatórios. Para cada uma das entidades, desenvolva um formulário de cadastro onde todos os registros cadastrados devem ser apresentados em uma tabela.”

Bem, não vou escrever um documento gigantesco, especificando todas as restrições, pois este é apenas um exemplo. Então vamos começar pelo nosso banco de dados. Vou utilizar o MySQL, mas você fica livre para usar o SGBD (Sistema Gerenciador de Banco de Dados) que quiser. Novamente, como o objetivo do tutorial é a integração Flex e Java, não vamos ficar entrando em detalhes relacionados à SQL. Sendo assim, segue a estrutura da base de dados do nosso sistema e o script em SQL (MySQL) para a criação da nossa base de dados, além de alguns registros já cadastrados.

 

Figura 1

Estrutura da base de dados do sistema de exemplo

 

SET FOREIGN_KEY_CHECKS=0;

CREATE DATABASE flexjava
    CHARACTER SET 'latin1'
    COLLATE 'latin1_swedish_ci';

USE flexjava;

CREATE TABLE estado (
  id int(11) NOT NULL AUTO_INCREMENT,
  nome varchar(50) NOT NULL,
  sigla varchar(2) NOT NULL,
  PRIMARY KEY (id),
  UNIQUE KEY sigla (sigla)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;

CREATE TABLE cidade (
  id int(11) NOT NULL AUTO_INCREMENT,
  nome varchar(50) NOT NULL,
  id_estado int(11) NOT NULL,
  PRIMARY KEY (id),
  KEY id_estado (id_estado),
  CONSTRAINT cidade_fk FOREIGN KEY (id_estado) REFERENCES estado (id) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=latin1;

CREATE TABLE cliente (
  id int(11) NOT NULL AUTO_INCREMENT,
  nome varchar(50) NOT NULL,
  sobrenome varchar(50) NOT NULL,
  cpf varchar(14) NOT NULL,
  dataNascimento timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  rua varchar(60) NOT NULL,
  numero varchar(8) NOT NULL,
  cep varchar(9) NOT NULL,
  id_cidade int(11) NOT NULL,
  PRIMARY KEY (id),
  UNIQUE KEY cpf (cpf),
  KEY id_cidade (id_cidade),
  CONSTRAINT cliente_fk FOREIGN KEY (id_cidade) REFERENCES cidade (id) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;

INSERT INTO `estado` (id, nome, sigla) VALUES
  (1,'São Paulo','SP'),
  (2,'Minas Gerais','MG'),
  (3,'Rio de Janeiro','RJ'),
  (4,'Paraná','PR');
COMMIT;

INSERT INTO `cidade` (id, nome, id_estado) VALUES
  (1,'Vargem Grande do Sul',1),
  (2,'São João da Boa Vista',1),
  (3,'São Paulo',1),
  (4,'Poços de Caldas',2),
  (5,'Belo Horizonte',2),
  (6,'Paraty',3),
  (7,'Rio de Janeiro',3),
  (8,'Curitiba',4),
  (9,'Maringá',4);
COMMIT;

INSERT INTO `cliente` (id, nome, sobrenome, cpf, dataNascimento, rua, numero, cep, id_cidade) VALUES
  (1,'David','Buzatto','123.456.789-12','1985-02-25 00:00:00','Rua Getúlio Vargas','123','13880-000',1),
  (2,'João','da Silva','456.789.123-25','1970-06-19 00:00:00','Rua dos Coqueiros','741','13880-000',1),
  (3,'Maria','do Bairro','789.123.456-45','1971-10-25 00:00:00','Rua dos Mexicanos','98','12345-456',8);
COMMIT;

Como você pode perceber pelo código SQL acima, a nossa base de dados terá o nome de “flexjava”. Sendo assim, carregue este script no seu SGBD para podermos dar continuidade.

Agora que já temos nossa base de dados, vamos ao NetBeans. Em “Source Code”, crie um novo pacote, com o nome de “entidades”. Vamos criar então três classes (Estado, Cliente e Cidade), uma para cada uma das tabelas. Essas classes serão nossas entidades. Elas devem mapear para o paradigma orientado a objetos suas contrapartes, ou seja, as tabelas do modelo relacional. Seguem então o código das três entidades, com os atributos e seus respectivos getters e os setters. Para poupar espaço, irei postar apenas os gets e os sets da entidade Estado.

entidades.Estado.java:

package entidades;

package entidades;

/**
 * Um Estado.
 *
 * @author David Buzatto
 */
public class Estado {

    private Long id;
    private String nome;
    private String sigla;

    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 getSigla() {
        return sigla;
    }

    public void setSigla( String sigla ) {
        this.sigla = sigla;
    }

}

entidades.Cidade.java:

package entidades;

/**
 * Uma Cidade.
 *
 * @author David Buzatto
 */
public class Cidade {

    private Long id;
    private String nome;
    private Estado estado;

    // getters e setters

}

entidades.Cliente.java:

package entidades;

import java.sql.Timestamp;

/**
 * Um Cliente.
 *
 * @author David Buzatto
 */
public class Cliente {

    private Long id;
    private String nome;
    private String sobrenome;
    private String cpf;
    private Timestamp dataNascimento;
    private String rua;
    private String numero;
    private String cep;
    private Cidade cidade;

    // getters e setters

}

Legal, temos nossas entidades, agora falta a nossa camada de persistência. Iremos utilizar o padrão DAO (Data Access Object), mas não vou ficar entrando em detalhes quanto a arquitetura, se o DAO está genérico o bastante, se vamos ter x camadas de abstração, etc. Se quiser informações quanto a esses assuntos arquiteturais, basta usar o Google 😉

Para começarmos, vamos criar dois novos pacotes no nosso projeto. Um com o nome de “jdbc” e outro com o nome de “dao”. Até o momento a estrutura do nosso projeto tem essa aparência:

 

Figura 2

Estrutura do projeto

 

Iremos iniciar pelo pacote jdbc, onde iremos criar uma fábrica de conexões, mas antes disso, precisamos fazer mais uma configuração no nosso projeto. Para que possamos utilizar o JDBC, precisamos colocar o driver do SGBD que estamos utilizando. No exemplo, como já dito, estou usando o MySQL. Lembra que na primeira parte deste tutorial, onde configuramos o NetBeans, nós criamos um projeto e informamos que queríamos que as nossas bibliotecas ficasses armazenadas dentro do projeto? Logo após isso, criamos a biblioteca para o BlazeDS e importamos os .jars. Por padrão, o NetBeans vem preconfigurado com diversas bibliotecas, mas como criamos um projeto com o nosso próprio escopo de bibliotecas, as bibliotecas padrão do NetBeans precisam ser importadas para que possamos utilizá-las. No nosso caso, iremos importar a biblioteca do driver do MySQL. Vamos lá então!

Procure na estrutura do projeto pela pasta de bibliotecas (Libraries). Clique com o botão direito e escolha “Add Library”. O diálogo “Add Library” vai aparecer.

 

Figura 3

Diálogo "Add Library"

 

Note que da primeira vez que utilizados esse diálogo, nós clicamos em “Create…”, pois nós criamos a nossa biblioteca, no caso, para o BlazeDS e suas dependências. Note que além do botão “Create…” existe o botão “Import”. É no botão “Import” que podemos importar as bibliotecas pré-definidas no NetBeans. Sendo assim, clique no botão “Import”. Assim que clicar, o diálogo “Import Library” vai aparecer. Procure pela biblioteca “MySQL JDBC Driver” e clique no botão “Import Library” logo abaixo.

 

Figura 4

Diálogo "Import Library"

 

Assim que clicar no botão, o diálogo “Add Library” vai reaparecer, só que agora vai conter a biblioteca do driver do MySQL que foi importada.

 

Figura 5

Biblioteca com o driver do MySQL importada

 

Selecione a bibiloteca e clique no botão “Add Library”. Perceba que agora, se você expandir a pasta “Libraries” do seu projeto, a biblioteca do driver do MySQL vai ter sido inserida.

 

Figura 6

Biblioteca do driver do MySQL inserida no projeto

 

Legal, com isso podemos agora usar o driver do MySQL para podermos conectar no SGBD através da nossa aplicação. Então voltemos ao código. Como eu disse, iremos criar uma fábrica de conexões, que será uma classe com um método estático que por sua vez será utilizado para criar conexões JDBC com o SGBD. Sendo assim, no pacote “jdbc” crie a classe “ConnectionFactory”. Acredito que você já tenha algum domínio sobre como utilizar o JDBC, mas mesmo assim inseri alguns comentários na implementação da classe, que pode ser vista abaixo:

jdbc.ConnectionFactory.java

package jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

/**
 * Uma fábrica de conexões.
 *
 * @author David Buzatto
 */
public class ConnectionFactory {

    /*
     * Este bloco estático será executado assim que esta classe for carregada,
     * sendo assim, será executado apenas uma vez.
     */
    static {
        try {
            /*
             * Carrega a classe com.mysql.jdbc.Driver, que é a implementação
             * do driver JDBC para o MySQL.
             */
            Class.forName( "com.mysql.jdbc.Driver" );

            // caso a classe não seja encontrada
        } catch ( ClassNotFoundException exc ) {

            /*
             * Como log usaremos o stacktrace das excessões, mas recomendo
             * que para um projeto real você utilize algum mecanismo de log
             * melhor, como o Log4J por exemplo.
             */
            exc.printStackTrace();

        }
    }

    /**
     * O método getConnection retorna uma conexão com o banco de dados baseado
     * nos parâmetros fornecidos.
     *
     * @param url O endereço da base de dados.
     * @param usuario O usuário que tem permissão na base de dados especificada.
     * @param senha A senha do usuário especificado
     * @return Uma conexão com o banco de dados especificado na url.
     * @throws SQLException Caso ocorra algum problema durante a conexão.
     */
    public static Connection getConnection(
            String url,
            String usuario,
            String senha ) throws SQLException {

        // retorna a conexão a partir do método getConnection de DriverManager
        return DriverManager.getConnection( url, usuario, senha );

    }

}

Os comentários no código da classe “ConnectionFactory” são suficientes para entendê-la. Vamos então aos nossos DAOs!

Para quem não conhece, resumidamente, o padrão de projeto DAO especifica um camada para trabalhar com a persistência dos dados de objetos na forma de registros em tabelas e a obtenção desses registros e a “conversão” deles novamente em objetos. Existem diversos frameworks que abstraem esse trabalho para o desenvolvedor, bastando criar as entidades e configurar o framework em questão para que ele consiga fazer essa conversão automática. Esses frameworks são chamados de frameworks ORM (Object-Relational Mapping), ou seja, servem como ponte entre o mundo dos objetos (uma linguagem OO) e o mundo relacional (um SBGD relacional). Um exemplo desse tipo de framework é o Hibernate, que provavelmente você há ouviu falar. Novamente vou bater na mesma tecla 😀 Neste tutorial só vamos trabalhar com a intergração Flex e Java, então vamos fazer quase tudo na mão. Cansou? Vamos ao código? Let’s go 😀

Nosso primeiro passo vai ser criar a classe “Dao” no pacote “dao”. Essa classe vai ser o nosso DAO genérico, que vai ser usado como modelo para os DAOs mais específicos (um para cada entidade). No nosso Dao, nós especificamos então quatro métodos, um para cada ação que podemos fazer nas nossas tabelas, ou seja, o famoso CRUD: Create (salvar; criar), Read (ler), Update (atualizar) e Delete (excluir; remover; deletar). Segue então o código do nosso DAO genérico.

dao.Dao.java

package dao;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import jdbc.ConnectionFactory;

/**
 * DAO genérico.
 *
 * @author David Buzatto
 */
public abstract class Dao<T extends Object> {

    // cada Dao terá uma conexão.
    private Connection conexao;

    /**
     * Construtor do Dao.
     * É nesse construtor que a conexão é criada.
     *
     * @throws SQLException
     */
    public Dao() throws SQLException {

        /*
         * Usa-se o método getConnection da fábrica de conexões,
         * passando o endereço da base (string/url de conexão), o nome do
         * usuário (no caso, "root") e a senha ("root" também).
         */
        conexao = ConnectionFactory.getConnection(
                "jdbc:mysql://localhost/flexjava",
                "root",
                "root" );

    }

    /**
     * Método para obter a conexão criada.
     *
     * @return Retorna a conexão.
     */
    public Connection getConnection() {
        return conexao;
    }

    /**
     * Método para fechar a conexão aberta.
     *
     * @throws SQLException Caso ocorra algum erro durante o fechamento da
     * conexão.
     */
    public void closeConnection() throws SQLException {
        conexao.close();
    }

    /**
     * Método abstrato para salvar uma instância de uma entidade da base de
     * dados.
     * É o "C" do CRUD.
     *
     * @param obj Instância do objeto da entidade a ser salvo.
     * @throws SQLException Caso ocorra algum erro durante a gravação.
     */
    public abstract void save( T obj ) throws SQLException;

    /**
     * Método abstrato para atualizar uma instância de uma entidade da base de
     * dados.
     * É o "U" do CRUD.
     *
     * @param obj Instância do objeto da entidade a ser atualizado.
     * @throws SQLException Caso ocorra algum erro durante a atualização.
     */
    public abstract void update( T obj ) throws SQLException;

    /**
     * Método abstrato para excluir uma instância de uma entidade da base de
     * dados.
     * É o "D" do CRUD.
     *
     * @param obj Instância do objeto da entidade a ser salvo.
     * @throws SQLException Caso ocorra algum erro durante a exclusão.
     */
    public abstract void delete( T obj ) throws SQLException;

    /**
     * Método abstrato para obter todas as instâncias de uma entidade da base
     * de dados.
     * É o "R" do CRUD.
     *
     * @return Lista de todas as instâncias da entidade.
     * @throws SQLException Caso ocorra algum erro durante a consulta.
     */
    public abstract List<T> listAll() throws SQLException;

}

Perceba que o sintax highlighting do componente de código fonte do WordPress não funciona muito bem, mas assim que você copiar para o NetBeans, vc vai ver que está correto. Note também que comentei todos os métodos e indiquei qual operação do CRUD eles representam. Perceba que para a operação “R” (read) podemos ter vários métodos, mas o padrão será o que lista tudo. Outro detalhe é que nosso Dao, quando for ser implementado (é uma classe abstrata!) deve ser especificado em cima de qual classe (entidade) ele vai atuar. O “T extends Object” siginifica que todo lugar onde existe “T” vai ser trocado pela a entidade que vai ser utilizada. Bem, pode estar um pouco confuso caso você nunca tenha usado os genéricos do Java, então vamos para o nosso primeiro DAO concreto, que será o EstadoDao.

Quando vamos estender uma classe abstrata, precisamos implementar todos os seus métodos (caso a classe que esteja estendendo for uma classe concreta). Primeiramente, no pacote “dao” crie a classe “EstadoDao”. Especifique que EstadoDao estende (extends) Dao<Estado>. Isso mesmo, Dao<Estado> ou seja, estende a classe Dao e o tipo genérico é Estado. Veja o código:

dao.EstadoDao.java

package dao;

import entidades.Estado;

/**
 * DAO para a entidade Estado.
 *
 * @author David Buzatto
 */
public class EstadoDao extends Dao<Estado> {

}

Perceba que o NetBeans vai reclamar, grifanto EstadoDao em vermelho, pois EstadoDao é uma classe concreta que está estendendo uma classe abstrata. Note também que uma lâmpada aparecerá na linha do erro. Clique nela, a opção “Implement All Abstract Methods” vai aparecer.

 

Figura 7

Erro ao estender o Dao que é uma classe abstrata

 

Clique na opção que apareceu. O NetBeans vai fornecer a implementação de todos os métodos, lançando uma excessão no corpo de cada um.  Posterirmente (já já) iremos substituir o “throw new UnsupportedOperationException( “…” )” pela a implementação específica do método. Perceba ainda que o NetBeans continua reclamando que tem um problema, só que a gora toda a linha da declaração da classe está vermelha. Se você passar o mouse em cima da linha para ler o erro, vai ver a seguinte mensagem:

“unreported exception java.sql.SQLException in default constructor”

Isso acontece porque o construtor padrão do nosso Dao cria uma conexão com o banco e pode lançar uma SQLException (que é uma excessão checada). Sendo assim, precisamos implementar o construtor padrão do nosso EstadoDao para informar que ele lança uma SQLException também, pois o construtor padrão de EstadoDao vai chamar implicitamente o construtor padrão de Dao, que por sua vez lança uma SQLException. Por enquanto, nosso EstadoDao está assim:

package dao;

import entidades.Estado;
import java.sql.SQLException;
import java.util.List;

/**
 * DAO para a entidade Estado.
 *
 * @author David Buzatto
 */
public class EstadoDao extends Dao<Estado> {

    public EstadoDao() throws SQLException {
    }

    // métodos CRUD aqui...

}

Vamos a implementação dos métodos CRUD. Basicamente iremos criar uma query, pegar os dados do objeto passado, popular essa query e executá-la. Para poupar tempo e explicações já vou postar o código dos três Daos que iremos ter. Acredito que com o código seja possível você entender o que está acontecendo. Qualquer dúvida, mande um comentário 😉

dao.EstadoDao.java

package dao;

import entidades.Estado;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * DAO para a entidade Estado.
 *
 * @author David Buzatto
 */
public class EstadoDao extends Dao<Estado> {

    public EstadoDao() throws SQLException {
    }

    @Override
    public void save( Estado obj ) throws SQLException {

        PreparedStatement stmt = getConnection().prepareStatement(
                "INSERT INTO "
                + "estado( nome, sigla ) "
                + "VALUES( ?, ? );" );

        stmt.setString( 1, obj.getNome() );
        stmt.setString( 2, obj.getSigla() );

        stmt.executeUpdate();
        stmt.close();

    }

    @Override
    public void update( Estado obj ) throws SQLException {

        PreparedStatement stmt = getConnection().prepareStatement(
                "UPDATE estado "
                + "SET"
                + "    nome = ?,"
                + "    sigla = ? "
                + "WHERE"
                + "    id = ?;" );

        stmt.setString( 1, obj.getNome() );
        stmt.setString( 2, obj.getSigla() );
        stmt.setLong( 3, obj.getId() );

        stmt.executeUpdate();
        stmt.close();

    }

    @Override
    public void delete( Estado obj ) throws SQLException {

        PreparedStatement stmt = getConnection().prepareStatement(
                "DELETE FROM estado "
                + "WHERE"
                + "    id = ?;" );

        stmt.setLong( 1, obj.getId() );

        stmt.executeUpdate();
        stmt.close();

    }

    @Override
    public List<Estado> listAll() throws SQLException {

        List<Estado> lista = new ArrayList<Estado>();

        PreparedStatement stmt = getConnection().prepareStatement(
                "SELECT * FROM estado;" );

        ResultSet rs = stmt.executeQuery();

        while ( rs.next() ) {

            Estado e = new Estado();

            e.setId( rs.getLong( "id" ) );
            e.setNome( rs.getString( "nome" ) );
            e.setSigla( rs.getString( "sigla" ) );

            lista.add( e );

        }

        rs.close();
        stmt.close();

        return lista;

    }

}

dao.CidadeDao.java

package dao;

import entidades.Cidade;
import entidades.Estado;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * DAO para a entidade Cidade.
 *
 * @author David Buzatto
 */
public class CidadeDao extends Dao<Cidade> {

    public CidadeDao() throws SQLException {
    }

    @Override
    public void save( Cidade obj ) throws SQLException {

        PreparedStatement stmt = getConnection().prepareStatement(
                "INSERT INTO "
                + "cidade( nome, id_estado ) "
                + "VALUES( ?, ? );" );

        stmt.setString( 1, obj.getNome() );
        stmt.setLong( 2, obj.getEstado().getId() );

        stmt.executeUpdate();
        stmt.close();

    }

    @Override
    public void update( Cidade obj ) throws SQLException {

        PreparedStatement stmt = getConnection().prepareStatement(
                "UPDATE cidade "
                + "SET"
                + "    nome = ?,"
                + "    id_estado = ? "
                + "WHERE"
                + "    id = ?;" );

        stmt.setString( 1, obj.getNome() );
        stmt.setLong( 2, obj.getEstado().getId() );
        stmt.setLong( 3, obj.getId() );

        stmt.executeUpdate();
        stmt.close();

    }

    @Override
    public void delete( Cidade obj ) throws SQLException {

        PreparedStatement stmt = getConnection().prepareStatement(
                "DELETE FROM cidade "
                + "WHERE"
                + "    id = ?;" );

        stmt.setLong( 1, obj.getId() );

        stmt.executeUpdate();
        stmt.close();

    }

    @Override
    public List<Cidade> listAll() throws SQLException {

        List<Cidade> lista = new ArrayList<Cidade>();

        PreparedStatement stmt = getConnection().prepareStatement(
                "SELECT "
                + "    c.id idCidade, "
                + "    c.nome nomeCidade, "
                + "    e.id idEstado, "
                + "    e.nome nomeEstado, "
                + "    e.sigla siglaEstado "
                + "FROM "
                + "    cidade c, "
                + "    estado e "
                + "WHERE"
                + "    c.id_estado = e.id;" );

        ResultSet rs = stmt.executeQuery();

        while ( rs.next() ) {

            Cidade c = new Cidade();
            Estado e = new Estado();

            c.setId( rs.getLong( "idCidade" ) );
            c.setNome( rs.getString( "nomeCidade" ) );
            c.setEstado( e );

            e.setId( rs.getLong( "idEstado" ) );
            e.setNome( rs.getString( "nomeEstado" ) );
            e.setSigla( rs.getString( "siglaEstado" ) );

            lista.add( c );

        }

        rs.close();
        stmt.close();

        return lista;

    }

}

dao.ClienteDao.java

package dao;

import entidades.Cidade;
import entidades.Cliente;
import entidades.Estado;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * DAO para a entidade Cliente.
 *
 * @author David Buzatto
 */
public class ClienteDao extends Dao<Cliente> {

    public ClienteDao() throws SQLException {
    }

    @Override
    public void save( Cliente obj ) throws SQLException {

        PreparedStatement stmt = getConnection().prepareStatement(
                "INSERT INTO "
                + "cliente( "
                + "    nome, "
                + "    sobrenome, "
                + "    cpf, "
                + "    dataNascimento, "
                + "    rua, "
                + "    numero, "
                + "    cep, "
                + "    id_cidade ) "
                + "VALUES( ?, ?, ?, ?, ?, ?, ?, ? );" );

        stmt.setString( 1, obj.getNome() );
        stmt.setString( 2, obj.getSobrenome() );
        stmt.setString( 3, obj.getCpf() );
        stmt.setTimestamp( 4, obj.getDataNascimento() );
        stmt.setString( 5, obj.getRua() );
        stmt.setString( 6, obj.getNumero() );
        stmt.setString( 7, obj.getCep() );
        stmt.setLong( 8, obj.getCidade().getId() );

        stmt.executeUpdate();
        stmt.close();

    }

    @Override
    public void update( Cliente obj ) throws SQLException {

        PreparedStatement stmt = getConnection().prepareStatement(
                "UPDATE cliente "
                + "SET"
                + "    nome = ?, "
                + "    sobrenome = ?,"
                + "    cpf = ?, "
                + "    dataNascimento = ?, "
                + "    rua = ?, "
                + "    numero = ?, "
                + "    cep = ?, "
                + "    id_cidade = ? "
                + "WHERE"
                + "    id = ?;" );

        stmt.setString( 1, obj.getNome() );
        stmt.setString( 2, obj.getSobrenome() );
        stmt.setString( 3, obj.getCpf() );
        stmt.setTimestamp( 4, obj.getDataNascimento() );
        stmt.setString( 5, obj.getRua() );
        stmt.setString( 6, obj.getNumero() );
        stmt.setString( 7, obj.getCep() );
        stmt.setLong( 8, obj.getCidade().getId() );
        stmt.setLong( 9, obj.getId() );

        stmt.executeUpdate();
        stmt.close();

    }

    @Override
    public void delete( Cliente obj ) throws SQLException {

        PreparedStatement stmt = getConnection().prepareStatement(
                "DELETE FROM cliente "
                + "WHERE"
                + "    id = ?;" );

        stmt.setLong( 1, obj.getId() );

        stmt.executeUpdate();
        stmt.close();

    }

    @Override
    public List<Cliente> listAll() throws SQLException {

        List<Cliente> lista = new ArrayList<Cliente>();

        PreparedStatement stmt = getConnection().prepareStatement(
                "SELECT "
                + "    c.id idCliente, "
                + "    c.nome nomeCliente, "
                + "    c.sobreNome sobrenomeCliente, "
                + "    c.cpf cpfCliente, "
                + "    c.dataNascimento dataNascimentoCliente, "
                + "    c.rua ruaCliente, "
                + "    c.numero numeroCliente, "
                + "    c.cep cepCliente, "
                + "    ci.id idCidade, "
                + "    ci.nome nomeCidade, "
                + "    e.id idEstado, "
                + "    e.nome nomeEstado, "
                + "    e.sigla siglaEstado "
                + "FROM "
                + "    cliente c, "
                + "    cidade ci, "
                + "    estado e "
                + "WHERE"
                + "    c.id_cidade = ci.id AND "
                + "    ci.id_estado = e.id;");

        ResultSet rs = stmt.executeQuery();

        while ( rs.next() ) {

            Cliente c = new Cliente();
            Cidade ci = new Cidade();
            Estado e = new Estado();

            c.setId( rs.getLong( "idCliente" ) );
            c.setNome( rs.getString( "nomeCliente" ) );
            c.setSobrenome( rs.getString( "sobrenomeCliente" ) );
            c.setCpf( rs.getString( "cpfCliente" ) );
            c.setDataNascimento( rs.getTimestamp( "dataNascimentoCliente" ) );
            c.setRua( rs.getString( "ruaCliente" ) );
            c.setNumero( rs.getString( "numeroCliente" ) );
            c.setCep( rs.getString( "cepCliente" ) );
            c.setCidade( ci );

            ci.setId( rs.getLong( "idCidade" ) );
            ci.setNome( rs.getString( "nomeCidade" ) );
            ci.setEstado( e );

            e.setId( rs.getLong( "idEstado" ) );
            e.setNome( rs.getString( "nomeEstado" ) );
            e.setSigla( rs.getString( "siglaEstado" ) );

            lista.add( c );

        }

        rs.close();
        stmt.close();

        return lista;

    }

}

Ufa! Quanto código hein? Quando fazemos tudo na mão temos muito trabalho, por isso um framework como o Hibernate pode nos ajudar muito! Enfim, com os DAOs prontos, precisamos agora criar os serviços e então terminaremos essa parte do tutorial! Vamos lá então.

Vamos usar uma abordagem parecida com a que usamos no nosso Dao genérico. Vamos criar um serviço genérico para trabalhar com entidades (EntityServices) e nele teremos novamente os quatro métodos CRUD. Dentro da implementação de cada um, criaremos o Dao correspondente e executaremos a operação correspondente ao serviço. Como há disse, a idéia é parecida com a do Dao, então, vou postar diretamente os códigos das quatro classes (EntityServices, EstadoServices, CidadeServices e ClienteServices).

servicos.EntityServices.java

package servicos;

import java.util.List;

/**
 * Classe abstrata que define a assinatura dos serviços para as entidades.
 *
 * @author David Buzatto
 */
public abstract class EntityServices<T extends Object> {

    /**
     * Método abstrato para salvar um objeto remoto.
     * Utiliza o método save do DAO correspondente.
     *
     * @param obj Objeto remoto a ser salvo.
     * @throws Exception Caso ocorra algum erro.
     */
    public abstract void save( T obj ) throws Exception;

    /**
     * Método abstrato para atualiar um objeto remoto.
     * Utiliza o método update do DAO correspondente.
     *
     * @param obj Objeto remoto a ser atualizado.
     * @throws Exception Caso ocorra algum erro.
     */
    public abstract void update( T obj ) throws Exception;

    /**
     * Método abstrato para excluir um objeto remoto.
     * Utiliza o método delete do DAO correspondente.
     *
     * @param obj Objeto remoto a ser excluído.
     * @throws Exception Caso ocorra algum erro.
     */
    public abstract void delete( T obj ) throws Exception;

    /**
     * Método abstrato para obter todas as intâncias de uma determinada
     * entidade e serializá-las em uma lista.
     * Utiliza o método listAll do DAO correspondente.
     *
     * @return Uma lista de objetos.
     * @throws Exception Caso ocorra algum erro.
     */
    public abstract List<T> listAll() throws Exception;

}

servicos.EstadoServices.java

package servicos;

import dao.Dao;
import dao.EstadoDao;
import entidades.Estado;
import java.util.List;

/**
 * Serviços para a entidade Estado.
 *
 * @author David Buzatto
 */
public class EstadoServices extends EntityServices<Estado> {

    @Override
    public void save( Estado obj ) throws Exception {
        Dao<Estado> dao = new EstadoDao();
        dao.save( obj );
        dao.closeConnection();
    }

    @Override
    public void update( Estado obj ) throws Exception {
        Dao<Estado> dao = new EstadoDao();
        dao.update( obj );
        dao.closeConnection();
    }

    @Override
    public void delete( Estado obj ) throws Exception {
        Dao<Estado> dao = new EstadoDao();
        dao.delete( obj );
        dao.closeConnection();
    }

    @Override
    public List<Estado> listAll() throws Exception {
        Dao<Estado> dao = new EstadoDao();
        List<Estado> lista = dao.listAll();
        dao.closeConnection();
        return lista;
    }

}

servicos.CidadeServices.java

package servicos;

import dao.Dao;
import dao.CidadeDao;
import entidades.Cidade;
import java.util.List;

/**
 * Serviços para a entidade Cidade.
 *
 * @author David Buzatto
 */
public class CidadeServices extends EntityServices<Cidade> {

    @Override
    public void save( Cidade obj ) throws Exception {
        Dao<Cidade> dao = new CidadeDao();
        dao.save( obj );
        dao.closeConnection();
    }

    @Override
    public void update( Cidade obj ) throws Exception {
        Dao<Cidade> dao = new CidadeDao();
        dao.update( obj );
        dao.closeConnection();
    }

    @Override
    public void delete( Cidade obj ) throws Exception {
        Dao<Cidade> dao = new CidadeDao();
        dao.delete( obj );
        dao.closeConnection();
    }

    @Override
    public List<Cidade> listAll() throws Exception {
        Dao<Cidade> dao = new CidadeDao();
        List<Cidade> lista = dao.listAll();
        dao.closeConnection();
        return lista;
    }

}

servicos.ClienteServices.java

package servicos;

import dao.Dao;
import dao.ClienteDao;
import entidades.Cliente;
import java.util.List;

/**
 * Serviços para a entidade Cliente.
 *
 * @author David Buzatto
 */
public class ClienteServices extends EntityServices<Cliente> {

    @Override
    public void save( Cliente obj ) throws Exception {
        Dao<Cliente> dao = new ClienteDao();
        dao.save( obj );
        dao.closeConnection();
    }

    @Override
    public void update( Cliente obj ) throws Exception {
        Dao<Cliente> dao = new ClienteDao();
        dao.update( obj );
        dao.closeConnection();
    }

    @Override
    public void delete( Cliente obj ) throws Exception {
        Dao<Cliente> dao = new ClienteDao();
        dao.delete( obj );
        dao.closeConnection();
    }

    @Override
    public List<Cliente> listAll() throws Exception {
        Dao<Cliente> dao = new ClienteDao();
        List<Cliente> lista = dao.listAll();
        dao.closeConnection();
        return lista;
    }

}

Poderíamos generalizar ainda mais nossa arquitetura, mas vamos ficar por aqui. Perceba que caso você deseje mudar o mecanismo de persistência, basta configurar o framework que vai utilizar e então mudar a implementação dos serviços. Agora, para terminar essa parte, vamos então configurar o nosso remoting-config.xml para apontar para as classes de serviços que acabamos de criar. Segue então o remoting-config.xml completo.

remoting-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<service id="remoting-service"
    class="flex.messaging.services.RemotingService">

    <adapters>
        <adapter-definition id="java-object" class="flex.messaging.services.remoting.adapters.JavaAdapter" default="true"/>
    </adapters>

    <default-channels>
        <channel ref="my-amf"/>
    </default-channels>

    <destination id="testeServicos">
        <properties>
            <source>servicos.ServicosTeste</source>
        </properties>
    </destination>

    <destination id="servicosCalculadora">
        <properties>
            <source>servicos.ServicosCalculadora</source>
        </properties>
    </destination>

    <destination id="estadoServices">
        <properties>
            <source>servicos.EstadoServices</source>
        </properties>
    </destination>

    <destination id="cidadeServices">
        <properties>
            <source>servicos.CidadeServices</source>
        </properties>
    </destination>

    <destination id="clienteServices">
        <properties>
            <source>servicos.ClienteServices</source>
        </properties>
    </destination>

</service>

Finalmente terminamos essa parte do tutorial. Ela nos deu bastante trabalho, principalmente por causa dos DAOs. Na próxima (e agora sim, a última!) parte do tutorial iremos integrar nossa interface criada no Flash Builder para fazermos tudo isso funcionar.

Então é isso, até amanhã!

Parte 1Parte 2Parte 3Parte 4.1Parte 4.2

Anúncios