jTable não funciona corretamente

11 respostas
Lei

Prezados,

estou desenvolvendo uma aplicação no NetBeans (desktop), o que em muito tem consumido meus dias de “folga”…já é o 3o ou 4o tópico que posto, pois minha dificuldade está elevada ao cubo.
Seguinte: o jTable não exibe os resultados de certa pesquisa…o referido código está no botão “Pesquisar”…alguém gostaria de indicar uma melhoria e me explicar a razão do não funcionamento deste?
Grata!
Lei

try{
            Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
            Connection cont = DriverManager.getConnection("jdbc:odbc:SSGB","","");
            Statement stm=cont.createStatement();
            ResultSet rs = stm.executeQuery ("SELECT Titulo,Tipo from Obra where Titulo like '%" + jTextField1.getText() + "%'");
            while(rs.next())  
            {
                Object[] Lin = new Object[2];     
                Lin[0] = rs.getString("Titulo");     
                Lin[1] = rs.getString("Tipo");     
            }
           
           cont.close();

11 Respostas

Linkel

Boa noite!
Seu código para mostrar o resultado da consulta é só isso?
Se for então está incompleto, e consequentemente, errado.
Primeiro você instancia o objeto jTable, informando dados sobre as colunas…
Depois você armazena todo o conteúdo dos registros retornados no ResultSet em vetores do tipo String[] (só uso esse tipo)…
E então seta os valores ao jTable…
Usando DefaultTableModel, segue um exemplo:

private void pesquisarRegistro() { DefaultTableModel modeloTabela = new DefaultTableModel(null, new String[] {"Nome do Cliente","Data de Nascimento"}); tabela.setModel(modeloTabela); tabela.setDefaultRenderer(Object.class, new CellRenderer()); // nesse método a conexão é instanciada de uma classe de conexão específica... conexao.conectar(); try { Statement stmt = conexao.con.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM Clientes WHERE nomeCli like '%"+editCliente.getText()+"%'"); while (rs.next()) { // implemente vetores do tipo String... String[] dados = new String[2]; dados[0] = rs.getString("nomeCli"); dados[1] = rs.getString("dataNascCli"); modeloTabela.addRow(dados); } rs.close(); stmt.close(); } catch (SQLException e) { e.printStackTrace(); } conexao.desconectar(); }
Não tem erro!
É só isso. Percebi que não utilizou uma classe de conexão separada… Isso não é bom, principalmente porque demandam instâncias frequentemente…
Se você interessar me peça por e-mail as classes mas úteis para esse fim…
Um abraço!

Lei

Oi Linkel!

Olha…sinto muito em informar que não funcionou viu…coloquei exatamente como seu exemplo, mas o erro que me aparece é> “Erro column not found”…o código ficou assim: (lembrando que estou fazendo no NetBeans e adicionei o componente jTable1 no form)

DefaultTableModel modeloTabela = new DefaultTableModel(null, new String[] {"Titulo","Tipo"});   
        jTable1.setModel(modeloTabela);   
        jTable1.setDefaultRenderer(Object.class, new TableCellRenderer() {

            @Override(isso foi adicionado automaticamente, senão não deixava o programa nem ser depurado)
            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
                throw new UnsupportedOperationException("Not supported yet.");
            }
        });(aqui acaba o Override)
        
        try{
            Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
            Connection cont = DriverManager.getConnection("jdbc:odbc:SSGB","","");
            Statement stm=cont.createStatement();
            ResultSet rs = stm.executeQuery ("SELECT Titulo,Tipo from Obra where Titulo like '%" + jTextField1.getText() + "%' order by Titulo");
            while (rs.next()) {   
              
            String[] dados = new String[2];   
            dados[0] = rs.getString("Título");   
            dados[1] = rs.getString("Tipo");   
            modeloTabela.addRow(dados);   
           
           cont.close();             
        
        } } catch (ClassNotFoundException ex) {
            Logger.getLogger(Pesqacervo.class.getName()).log(Level.SEVERE, null, ex);
        }   catch (SQLException e) {
            JOptionPane.showMessageDialog(this, "Erro"+e.getMessage());

    }                                        
  
    }

Q vida…

Obrigado!

Linkel

Bom dia.
Desculpe-me, eu digitei na hora e me esqueci que uso para todas as minhas jTables uma classe de renderização de células para dar o efeito “zebrado” às linhas… É só você tirar a linha que implementa sua instância…
Lembrando que, para utilizar o DefautlTableModel você têm que importá-lo antes:

Ficando assim:

private void pesquisarRegistro() { DefaultTableModel modeloTabela = new DefaultTableModel(null, new String[] {"Nome do Cliente","Data de Nascimento"}); tabela.setModel(modeloTabela); // a linha que estava aqui foi apagada... conexao.conectar(); try { Statement stmt = conexao.con.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM Clientes WHERE nomeCli like '%"+editCliente.getText()+"%'"); while (rs.next()) { // implemente vetores do tipo String... String[] dados = new String[2]; dados[0] = rs.getString("nomeCli"); dados[1] = rs.getString("dataNascCli"); modeloTabela.addRow(dados); } rs.close(); stmt.close(); } catch (SQLException e) { e.printStackTrace(); } conexao.desconectar(); }
Agora vai funcionar, rsrsrs…
Só completando, mesmo resolvendo esse erro, com esse código, ainda assim obteria-se erro de coluna não encontrada, mas no banco de dados; porque na sua linha “dados[0] = rs.getString(“Título”);”, o campo “Título” está com assento no i…

Espero que agora resolva seu problema.
Um grande abraço!

Lei

Menino…eu nem tinha reparado o acento…que mancada hein!
Deu super certo! Ficou lindo!

Aproveitando sua boa vontade…mais um pedido de ajuda: o registro que o usuário selecionar dará a ele a opção de alterar ou deletar registro do banco de dados.
Como eu codifico o alterar e o delete? Vc tem indicação de algum tutorial onde eu possa encontrar isso?

Muitíssimo obrigado mais uma vez! Espero poder retribuir de alguma forma!

Leila

Linkel

"... Isto fica feliz em lhe ser útil...", rsrsrsr...

Bom, quanto à implementação de alteração ou exclusão do registro selecionado na jTable, você precisa obter os valores chaves das células específicas segundo a seleção da jTable... Para ser mais claro: Considerando que você queira editar um registro selecionado com campos separados em jTextField's, para melhor desenvoltura da interface, e depois gravar as alterações para esse registro, ou queira simplesmente deletar o registro selecionado, segue exemplo...
// no evento Mouse Clicked da jTable...
    private void tabelaReligioesMouseClicked(java.awt.event.MouseEvent evt) {                                             
        if (tabelaReligioes.isEnabled()) {
            // captura o valor da primeira célula (com índice 0 na linha) e armazena na variável String religiao...
            religiao = (String) tabelaReligioes.getValueAt(tabelaReligioes.getSelectedRow(),0);
            // poderíamos jogar diretamente o conteúdo dessa variável ao jTextField correspondente,
            // porém é melhor testificar o valor com uma consulta ao banco de dados...
            conexao.conectar();
            try {
                stmt = conexao.con.createStatement();
                rs = stmt.executeQuery("Select * from Religioes where Nome_Reli = '"+religiao+"'");
                if (rs.next()) {
                    // joga para o edit o valor obtido da consulta...
                    editReligiao.setText(rs.getString("Nome_Reli"));
                    // observe que aqui se obtém o código do registro selecionado para melhor referência...
                    codReligiao = rs.getInt("Cod_Reli");
                }
                rs.close();
                stmt.close();
            }
            catch (SQLException ex) {
                ex.printStackTrace();
            }
            conexao.desconectar();
        }
    } 

// uma vez obtido o código (ou campo chave/único) é só implementar os métodos de alteração ou exclusão fazendo referência à esse código... 
    // método exemplo para alterações de registro...
    private void alterarRegistro() {
        conexao.conectar();
        try {
            stmt = conexao.con.createStatement();
            stmt.executeUpdate("Update Religioes set Nome_Reli = '"+editReligiao.getText()+"' where Cod_Reli = "+codReligiao);
            stmt.close();
            JOptionPane.showMessageDialog(this,"Alteração efetuada com sucesso!");
        }
        catch (SQLException e) {
            JOptionPane.showMessageDialog(this,"Erro na alteração do registro!");
            e.printStackTrace();
        }
        conexao.desconectar();
    }

    // método exemplo para exclusões de registro...
    private void excluirRegistro() {
        conexao.conectar();
        try {
            stmt = conexao.con.createStatement();
            stmt.executeUpdate("Delete from Religioes where Cod_Reli = "+codReligiao);
            stmt.close();
            JOptionPane.showMessageDialog(this,"Exclusão efetuada com sucesso!");
        }
        catch (SQLException e) {
            JOptionPane.showMessageDialog(this,"Erro na exclusão do registro!");
            e.printStackTrace();
        }
        conexao.desconectar();
    }
Entendeu? Super simples. Implemente à sua maneira e me retorne o resultado, por favor. Acho que vai te ajudar... Um abraço!
Lei

Bendito seja Deus que pôs Linkel na minha vida! Glória a Deus pela sua vida, moço!
Cara, Deus te usou pra tirar um peso da minha vida estudantil…vc não tem noção! Não tem como eu te agradecer!
Deu super certo, o programa está lindo, e tirei o total!

Implementação Excluir
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        // TODO add your handling code here:
       try{
            Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
            Connection cont = DriverManager.getConnection("jdbc:odbc:SSGB","","");
            Statement stm=cont.createStatement();
            
            stm.executeUpdate("DELETE from Obra where Codigo="+jTextField9.getText()+";");
            JOptionPane.showMessageDialog(this, "Exclusão efetuada com sucesso!");
            cont.close();
            stm.close();
            }
        catch (SQLException e) {
            JOptionPane.showMessageDialog(this, "Erro na exclusão! "+e.getMessage());
        } catch (ClassNotFoundException e) {
            JOptionPane.showMessageDialog(this, "Problemas de localização do driver!");
        } 
        
    }                 

Implementação Alterar
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        // TODO add your handling code here:
            String Titulo=jTextField3.getText();
            String Autor1=(String) jComboBox1.getSelectedItem();
            String Autor2=(String) jComboBox2.getSelectedItem();
            String Autor3=(String) jComboBox3.getSelectedItem();
            String Localizacao=(String) jComboBox4.getSelectedItem();
            String Editora=(String) jComboBox6.getSelectedItem();
            int Edicao=Integer.parseInt(jTextField4.getText());
            int Ano=Integer.parseInt(jTextField5.getText());
            int Numero=Integer.parseInt(jTextField6.getText());
            int Volume=Integer.parseInt(jTextField7.getText());
            int Codigo=Integer.parseInt(jTextField9.getText());
            String DataPublicacao=jTextField2.getText();
            ButtonModel Tipo=buttonGroup1.getSelection();
           
        try{
            Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
            Connection cont = DriverManager.getConnection("jdbc:odbc:SSGB","","");
            Statement stm=cont.createStatement();
            
            stm.executeUpdate("UPDATE Obra set Titulo='"+jTextField3.getText()+"',Autor1='"+jComboBox1.getSelectedItem()+"',Autor2='"+jComboBox2.getSelectedItem()+"',Autor3='"+jComboBox3.getSelectedItem()+"',Localizacao='"+jComboBox4.getSelectedItem()+"',Editora='"+jComboBox6.getSelectedItem()+"',Edicao='"+jTextField4.getText()+"',Ano='"+jTextField5.getText()+"',Numero='"+jTextField6.getText()+"',Volume='"+jTextField7.getText()+"',DataPublicacao='"+jTextField2.getText()+"',Tipo='"+buttonGroup1.getSelection()+"' where Codigo="+jTextField9.getText()+";");
            JOptionPane.showMessageDialog(this, "Dados alterados com sucesso!");
            cont.close();
            stm.close();
            }
        catch (SQLException e) {
            JOptionPane.showMessageDialog(this, "Erro"+e.getMessage());
        } catch (ClassNotFoundException e) {
            JOptionPane.showMessageDialog(this, "Problemas de localização do driver!");
        }
            
        
    }

Muitíssimo obrigado!!!
Leila

ViniGodoy

Bom, cheguei tarde nessa thread.

Ainda assim vale algumas dicas, que vão te facilitar muito o desenvolvimento:

  1. Não utilize o DefaultTableModel. Prefira sempre fazer o seu próprio model, filho de AbstractTableModel. O código fica mais limpo, mais fácil e mais claro;
  2. Sempre feche conexões com banco de dados dentro de um bloco finally. Caso contrário, em caso de erro elas podem ficar abertas;
  3. Quando capturar uma exceção, mostre a mensagem de erro para o usuário, mas grave em algum lugar o stack trace da exceção. É muito importante que você consiga dizer ao seu usuário porque um erro ocorreu.
  4. No lugar de concatenar coisas no seu SQL assim:

Procure usar PreparedStatements. Evitam muitas dores de cabeça e são mais seguros. No caso dos SQLs ali em cima, você pode correr o risco de um ataque chamado SQL Injection.

No mais, parabéns. Seu programa ficou legal. Só da próxima vez que for postar código no GUJ, deixe-o formatadinho usando a tag code. Como você é nova por aqui, não deve ainda saber fazer isso, então dá uma lida nesse tópico:
http://www.guj.com.br/posts/list/50115.java

Ele ensina a usar esse e outros recursos do fórum. :slight_smile:

Lei

Ai Vinícius…foi mal…eu realmente não sabia usar as tags BB…

Desculpe mesmo!
Vou refazer esses códigos…

Mas sabe, estou muito feliz pq foi a primeira vez, desde que comecei nessa área, em 2001, que consegui fazer um programa sozinha, do começo ao fim, com TODAS as funções solicitadas pelo professor. Eu já desisti da área pois nunca consegui emprego nem como estagiária, o que muito me desmotivou (claro, recusei algumas ofertas de estágio pois não recebia boas dicas de tais empresas, dadas por amigos).

Te agradeço demais pelas dicas e obrigado pelo “Seu programa ficou legal”!

Abraços!
Leila

Linkel

É isso aí, Leila!!!
Novamente fico feliz em ter te ajudado…
Concordo parcialmente com nosso saudoso amigo ViniGodoy…
Não vejo porque ter que fazer meu próprio Model se quero apenas listagens; então fica inviável dizer com tanta imperatividade:
“Não utilize o DefaultTableModel”. Não tem nada de mais limpo, mais fácil e mais claro nessa situação. É questão de preferência.
Gostei da dica de encerrar conexões dentro de um bloco finally e também de se gravar os erros em tempo de execução para uma posterior
manutenção…
Não concordo com a imposição do PreparedStatements. Afirmando desse jeito implica uma questão de mania… A lógica de programação está aí
para ser usada; tentar cortar caminho pode não ser acabar com as dores de cabeça ou simplesmente uma questão de segurança…

Não se preocupe com detalhes de formatação como uma regra irrefutável…
Seja tão bem vinda ao fórum com formatações ou não!
No mais, um grande abraço, Leila!

__
Lindoélio Lázaro

ViniGodoy

Linkel:
Não vejo porque ter que fazer meu próprio Model se quero apenas listagens; então fica inviável dizer com tanta imperatividade:
“Não utilize o DefaultTableModel”. Não tem nada de mais limpo, mais fácil e mais claro nessa situação. É questão de preferência.
Gostei da dica de encerrar conexões dentro de um bloco finally e também de se gravar os erros em tempo de execução para uma posterior
manutenção…

Eu preparei um model genérico, para o caso das listagens. Ele trabalha usando um List, que pode ser de um tipo arbitrário e é muito mais limpo do que o DefaultTableModel e um enum que descreve as colunas. De maneira geral, só pelo fato de você não ter que desmembrar suas classes em vetores já é de grande ajuda. E mais ainda, se você tiver que atualizar dados.

Eu realmente nunca vi, em todos os anos de programador java, um código que ficasse mais bem estruturado usando o DefaultTableModel, exceto se vc quiser listar um conteúdo de um vetor - o que quase nunca acontece (geralmente queremos listar objetos).

Não é uma questão de mania. Além de ser geralmente mais eficiente (pois permite que o BD pre-compile a query antes de executa-la) e gerar um código menos confuso (especialmente em sqls grandes e com muitos critérios), ele é a única maneira de prevenir ataques como o de SQL Injection. Na verdade, eu mesmo uso o Spring quando query trabalhar com queries de maneira mais direta. Ele fornece uma maneira muito melhor de trabalhar com ResultSets, já considerando os PreparedStatements e fechando conexões automaticamente.

Linkel:
Não se preocupe com detalhes de formatação como uma regra irrefutável…
Seja tão bem vinda ao fórum com formatações ou não!

Realmente, não era uma bronca… só uma dica! :slight_smile:
Ajuda muito o código formatado e tem gente que chega a ser grosseira se você não usar.

Linkel

Aí, amigo Vinícios…
Nada contra você não…
Aliás você já me ajudou muito em alguns tópicos aqui do guj…
Mas cada um tem sua experiência, suas preferências e seus motivos…
Por isso critico aqueles que impões verdades como absolutas…
Um abraço!

Criado 22 de março de 2008
Ultima resposta 27 de mar. de 2008
Respostas 11
Participantes 3