Modo correto de Programar utilizando ResultSet - SQLServer

olá pessoal, estou com algumas duvidas em relação a O.O. e Java
(eu programo em VBA apenas e o modo que eu programo em VBA é logicamente diferente…)

Minhas dúvidas são as seguintes:

  1. Quando carrego um SELECT em um ResultSet, estou carregando todos os dados do resultado da query nela certo?
    pois estou fazendo uma Agenda para mim, e tenho uma tela de Contatos que tem 3 componentes essenciais:
  • uma JComboBox para localizar os contatos
  • uma JTable para mostrar os telefones do contato que está na tela
  • e os Campos JTextField, para as informações do contato

e acabo fazendo alguns ResultSet’s, um para cada ocasião… :frowning:

  1. A estrutura que montei, não sei, está de acordo com a programação O.O e com os padrões do JAVA?

Minha Estrutura:

Packages:
ClassesDeNegocio - onde eu guardo as classes que ficam os atributos, as querys, getters e setters, métodos do banco (Insert, Update…)
ClassesDeServiço - onde eu guardo algumas classes que me ajudam na programação (métodos que contam registros, métodos para manipulação de datas…etc.)
ClassesDeTela - aqui ficam os JFrames

Interfaces:
Na classe de Padronização, eu criei uma interface, para sempre que eu criar uma classe de negocio, ter que implementar os métodos de banco (Update, Insert, Salvar(que decide se é update ou insert))

agora vejam o código da minha ClasseDeNegocio Contato:

[code]package ClassesDeNegocio;
import ClassesDeServico.Funcionalidade;
import ClassesDeServico.Padronizacao;
import ClassesDeServico.TratarErro;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class Contato implements Padronizacao.InterPadraoBanco{

//<editor-fold defaultstate="collapsed" desc="Variáveis de instância">
private int pessoaID;
private String nome;
private String sexo;
private String endereco;
private String numero;
private String bairro;
private String complemento;
private String cep;
private String cidade;
private String observacao;
private String uf;
private java.sql.Date dataDeNascimento;
private java.sql.Date dataDoCadastro;
private boolean cliente;
private boolean fornecedor;
private boolean contato;
private String [] lstPessoa;

public ResultSet rsTela;
//</editor-fold>

//<editor-fold defaultstate="collapsed" desc="GetSet">
public String[] getLstPessoa() {
    return lstPessoa;
}

public void setLstPessoa(String[] lstPessoa) {
    this.lstPessoa = lstPessoa;
}

public String getBairro() {
    return bairro;
}

public void setBairro(String bairro) {
    this.bairro = bairro;
}

public String getCep() {
    return cep;
}

public void setCep(String cep) {
    this.cep = cep;
}

public String getCidade() {
    return cidade;
}

public void setCidade(String cidade) {
    this.cidade = cidade;
}

public boolean isCliente() {
    return cliente;
}

public void setCliente(boolean cliente) {
    this.cliente = cliente;
}

public String getComplemento() {
    return complemento;
}

public void setComplemento(String complemento) {
    this.complemento = complemento;
}

public boolean isContato() {
    return contato;
}

public void setContato(boolean contato) {
    this.contato = contato;
}

public Date getDataDeNascimento() {
    return dataDeNascimento;
}

public void setDataDeNascimento(Date dataDeNascimento) {
    this.dataDeNascimento = dataDeNascimento;
}

public Date getDataDoCadastro() {
    return dataDoCadastro;
}

public void setDataDoCadastro(Date dataDoCadastro) {
    this.dataDoCadastro = dataDoCadastro;
}

public String getEndereco() {
    return endereco;
}

public void setEndereco(String endereco) {
    this.endereco = endereco;
}

public boolean isFornecedor() {
    return fornecedor;
}

public void setFornecedor(boolean fornecedor) {
    this.fornecedor = fornecedor;
}

public String getNome() {
    return nome;
}

public void setNome(String nome) {
    this.nome = nome;
}

public String getNumero() {
    return numero;
}

public void setNumero(String numero) {
    this.numero = numero;
}

public String getObservacao() {
    return observacao;
}

public void setObservacao(String observacao) {
    this.observacao = observacao;
}

public int getPessoaID() {
    return pessoaID;
}

public void setPessoaID(int pessoaID) {
    this.pessoaID = pessoaID;
}

public String getSexo() {
    return sexo;
}

public void setSexo(String sexo) {
    this.sexo = sexo;
}

public String getUf() {
    return uf;
}

public void setUf(String uf) {
    this.uf = uf;
}
//</editor-fold>

//<editor-fold defaultstate="collapsed" desc="setInsert">
@Override
public void setInsert(){
    try {            
        PreparedStatement ps =  Base.connection.prepareStatement(
                "INSERT INTO [tblPessoa]"
                + " ([Nome]"
                + " ,[Sexo]"
                + " ,[Endereco]"
                + " ,[Numero]"
                + " ,[Bairro]"
                + " ,[Complemento]"
                + " ,[CEP]"
                + " ,[Cidade]"
                + " ,[Observacao]"
                + " ,[UF]"
                + " ,[DataDeNascimento]"
                + " ,[DataDoCadastro]"
                + " ,[Cliente]"
                + " ,[Fornecedor]"
                + " ,[Contato])"
                + " VALUES"
                + " (? "//1 - Nome
                + " ,? "//2 - Sexo
                + " ,? "//3 - Endereco
                + " ,? "//4 - Numero
                + " ,? "//5 - Bairro
                + " ,? "//6 - Complemento
                + " ,? "//7 - CEP
                + " ,? "//8 - Cidade
                + " ,? "//9 - Observacao
                + " ,? "//10 - UF
                + " ,? "//11 - DataDeNascimento
                + " ,? "//12 - DataDoCadastro
                + " ,? "//13 - Cliente
                + " ,? "//14 - Fornecedor
                + " ,? )"//15 - Contato
                );
        
        ps.setString(1, nome);
        ps.setString(2, sexo);
        ps.setString(3, endereco);
        ps.setString(4, numero);
        ps.setString(5, bairro);
        ps.setString(6, complemento);
        ps.setString(7, cep);
        ps.setString(8, cidade);
        ps.setString(9, observacao);
        ps.setString(10, uf);
        ps.setDate(11, dataDeNascimento);
        ps.setDate(12, dataDoCadastro);
        ps.setInt(13, Funcionalidade.setConverterBooleanEmInt(cliente));
        ps.setInt(14, Funcionalidade.setConverterBooleanEmInt(fornecedor));
        ps.setInt(15, Funcionalidade.setConverterBooleanEmInt(contato));
        
        ps.executeUpdate();
    }
    catch (SQLException ex) {
        TratarErro.setSisErro(ex.getErrorCode(), ex.getMessage());
    }
}
//</editor-fold>

//<editor-fold defaultstate="collapsed" desc="setUpdate">
@Override
public void setUpdate(){    
    try{
        PreparedStatement ps =  Base.connection.prepareStatement(
                "UPDATE [tblPessoa]"
                + "SET [Nome] = ? "
                + ",[Sexo] = ? "
                + ",[Endereco] = ? "
                + ",[Numero] = ? "
                + ",[Bairro] = ? "
                + ",[Complemento] = ? "
                + ",[CEP] = ? "
                + ",[Cidade] = ? "
                + ",[Observacao] = ? "
                + ",[UF] = ? "
                + ",[DataDeNascimento] = ? "
                + ",[DataDoCadastro] = ? "
                + ",[Cliente] = ? "
                + ",[Fornecedor] = ? "
                + ",[Contato] = ? "
                + " WHERE PessoaID =  ? "//16 - pessoaID
                );
        
        ps.setString(1, nome);
        ps.setString(2, sexo);
        ps.setString(3, endereco);
        ps.setString(4, numero);
        ps.setString(5, bairro);
        ps.setString(6, complemento);
        ps.setString(7, cep);
        ps.setString(8, cidade);
        ps.setString(9, observacao);
        ps.setString(10, uf);
        ps.setDate(11, dataDeNascimento);
        ps.setDate(12, dataDoCadastro);
        ps.setInt(13, Funcionalidade.setConverterBooleanEmInt(cliente));
        ps.setInt(14, Funcionalidade.setConverterBooleanEmInt(fornecedor));
        ps.setInt(15, Funcionalidade.setConverterBooleanEmInt(contato));
        ps.setInt(16, pessoaID);
        
        ps.executeUpdate();
        Base.desconectar();            
    }catch(SQLException ex){
        TratarErro.setSisErro(ex.getErrorCode(), ex.getMessage());
    }
}
//</editor-fold>

//<editor-fold defaultstate="collapsed" desc="setSalvar">
@Override
public void setSalvar(String id){

    String sql = "SELECT PessoaID FROM tblPessoa WHERE PessoaID = " + id;
    try 
    {
        Base.conectar();
        ResultSet rsSalvar = Base.statement.executeQuery(sql);
            if(Funcionalidade.getQuantidadeDeRegistros(rsSalvar) == 0)
                setInsert();
            else
                setUpdate();
    } 
    catch (SQLException ex) 
    {
        TratarErro.setSisErro(ex.getErrorCode(), ex.getSQLState());
    }
}
//</editor-fold>

//<editor-fold defaultstate="collapsed" desc="Método Construtor">
public Contato(){
    carregarTela();
    carregarPessoasCombo();
}
//</editor-fold>

//<editor-fold defaultstate="collapsed" desc="Metodo de Carregamento da tela">
private void carregarTela(){
    String sql = "SELECT [PessoaID]"
            + " ,[Nome]"
            + " ,[Sexo]"
            + " ,[Endereco]"
            + " ,[Numero]"
            + " ,[Bairro]"
            + " ,[Complemento]"
            + " ,[CEP]"
            + " ,[Cidade]"
            + " ,[Observacao]"
            + " ,[UF]"
            + " ,[DataDeNascimento]"
            + " ,[DataDoCadastro]"
            + " ,[Cliente]"
            + " ,[Fornecedor]"
            + " ,[Contato]"
            + " FROM tblPessoa"
            + " ORDER BY PessoaID";
    try{
        Base.conectar();
        rsTela = Base.statement.executeQuery(sql);
        rsTela.first();
    }
    catch(SQLException ex){
        TratarErro.setSisErro(ex.getErrorCode(), ex.getSQLState());
    }
}
//</editor-fold>

//<editor-fold defaultstate="collapsed" desc="Métodos para carregar componentes">
private void carregarPessoasCombo(){
    int i = 0;
    String sql = "SELECT Nome,PessoaID FROM tblPessoa ORDER BY PessoaID";
    try {
        Base.conectar();
        ResultSet rsComboPessoa = Base.statement.executeQuery(sql);
        lstPessoa = new String[Funcionalidade.getQuantidadeDeRegistros(rsComboPessoa)];
        rsComboPessoa.beforeFirst();
        
        while(rsComboPessoa.next()){
            lstPessoa[i++] = rsComboPessoa.getInt("PessoaID") + "     " + rsComboPessoa.getString("Nome");
        }
        Base.desconectar(rsComboPessoa);
    } catch (SQLException ex) {
        TratarErro.setSisErro(ex.getErrorCode(), ex.getSQLState());
    }
}
//</editor-fold>

}[/code]

até acho que está bonitinho, maaaas, tenho vários ResultSet, tenho um gato ali no carregarPessoasCombo() aonde eu concateno o ID só para fazer a busca! hehe
eu preciso de tudo isso que faço?
eu deveria apenas carregar todos os dados em um ResultSet e depois manipula-los?

muita pergunta né??rsrs

Está funcional, mas para ficar OO e mais correto, você precisa:

  1. Criar classes de negócios para representar suas entidades (classe Pessoa, Endereco, etc.);
  2. Criar uma classe exclusiva para manipulação dessas classes no banco (PessoaDao, EnderecoDao, etc.);
  3. Fazer com que essas classes carreguem os dados em listas, do respectivo tipo da classe que representam;
  4. Fechar o ResultSet, o Statement e a Conexão, preferencialmente dentro de um bloco finally.
  5. Usar um Pool de conexões.

Pontos positivos da sua implementação:

  1. Você já usa PreparedStatement;
  2. Seu código está bem estruturado, para um sistema não OO;

Ao modificar, você poderá ter a combo preenchida com objetos do tipo Pessoa, o que eliminará a necessidade de concatenar o ID.
A JTable também funciona melhor com objetos, como vc pode ver nos links da minha assinatura (não use DefaultTableModel).

Finalmente, quando for abrir tópicos, procure ler a lista de tópicos com atenção. Você abriu em Java Básico. Seu tópico se encaixa mais no fórum de persistência. Vou move-lo.

Obrigado VinyGodoy

  1. Então a classe de negocio separo em um package
    nessa classe terei, as variaveis de instancia, o encapsulamento das mesmas, e só?

  2. Ai nessa outra package, terei os inserts, updates, selects para carregar componentes, etc… (DAO?)

  3. beleza…

  4. Hoje eu fecho o ResultSet, depois que acabo de fazer o procedimento, só quando se trata de fechar o ResultSet que carregou a tela, eu fecho ele quando fecho a tela, vou ver como consigo melhorar nisso

  5. Isso não sei como é, vou pesquisar sobre tal

Obrigado pelos pontos positivos, eu pesquisei sobre PrepraredStatement, quando estudava SQL Injection…

é verdade, nem me liguei que a Combo armazena objetos (e olha que eu via isso quando ia recuperar o qu estava escrito!(rsrs))
sobre a JTable, eu faço como voce falou pra não fazer: DefaultTableModel

[code] private void carregarTelefonesJTable(String pessoaNaTela){
lstColunaTelefone = new String[]{“Meio de Comunicação”,“Comunicação”,“Especificação”};
int i = 0;

            if (pessoaNaTela.equals(""))
                pessoaNaTela = "1";
            
    String sql = "SELECT [MeioComunicacao],[Comunicacao],[Especificacao]"
            + " FROM [tblPessoaComunicacao]"
            + " WHERE PessoaID = " + pessoaNaTela;
    
    try
    {
        Base.conectar();
        ResultSet rsPessoaComunicacao = Base.statement.executeQuery(sql);
        lstPessoaTelefone = new String[Funcionalidade.getQuantidadeDeRegistros(rsPessoaComunicacao)][lstColunaTelefone.length];
        rsPessoaComunicacao.beforeFirst();
        
        while(rsPessoaComunicacao.next()){
            lstPessoaTelefone [i][0] = rsPessoaComunicacao.getString("MeioComunicacao");
            lstPessoaTelefone [i][1] = rsPessoaComunicacao.getString("Comunicacao");
            lstPessoaTelefone [i++][2] = rsPessoaComunicacao.getString("Especificacao");
        }
        
        Base.desconectar(rsPessoaComunicacao);
    }
    catch (SQLException ex) {
        TratarErro.setSisErro(ex.getErrorCode(), ex.getSQLState());
    }
}[/code]

vi os links que me levaram na sua assinatura, é meio complicadinho hein…rsrs…criar na mão a bagaça!
mas se vai me permitir uma melhor manipulação da JTable, bem melhor, achei dificil mesmo mexer com JTable

eu coloquei nesse tópico, por não achar que se trata apenas de JDBC, e sim mais de OO!! :oops:

Ah, ok, sem problemas.

Não se assuste com o código do JTable. Parece complicado, mas na prática, você terá menos trabalho e menos dor de cabeça do que se usar o DefaultTableModel. Sem falar que quando você entender o que o código faz, vai ver que é até mais simples do que ficar copiando dados dos seus objetos para o model, e tentando sincronizar as duas coisas depois.