Sistema JAVA lento com: Firebird + Rede Windows

57 respostas
Z

Bom dia andei pesquisando aki pelo fórum mas nao consegui nada de concreto.

to usando um sistema desktop java e o banco de dados está em um servidor rodando windows e o firebird apenas, na estação cliente o sistema demora para abrir determinandas janelas onde carrega-se ao abrir jtables e/ou jcombobox com informações. Li que se eu usar PreparedStatement ao invés de Statement fica bem mais rápido, mas nao estou consguindo implementar no meu sistema.

deem uma olhada:

tentei colocar PreparedStatement como vcs podem ver abaixo

package db;

import java.sql.*;
import javax.swing.*;
import java.io.*;

public class ConexaoDB_Principal{
    //pega a unidade instalada
    File pasta = new File(System.getProperty("user.home"));
    String[] disco = pasta.toString().split(":");

    String ip;
    //conexao com FIREBIRD LOCAL
    String driver = "org.firebirdsql.jdbc.FBDriver";
    //String url = "jdbc:firebirdsql:"+ip+":c:\\gerenciador_extratos\\DB.GDB";
    String usuario = "SYSDBA";
    String senha = "masterkey"; /**/
    private Connection conexao;
    public PreparedStatement statement;
    public ResultSet resultset;

    public boolean conecta()
    {
      try {
      // Gravando no arquivo
      byte[] buffer = new byte[1000];
      InputStream in;
      try {
         in = new FileInputStream(disco[0]+":\\GesObras\\ConfigIP.txt");
         in.read(buffer);
         String temp = new String(buffer).trim().toString();
         ip = temp;
         in.close();
      } catch (FileNotFoundException e) {
         System.out.println(e);
      }
      catch (IOException e) {
         System.out.println(e);
      }

      }
      catch (Exception ee) {
          System.out.print(ee);
      }
        boolean result = true;
        try
        {
            Class.forName(driver);
            conexao = DriverManager.getConnection("jdbc:firebirdsql:"+ip+":"+disco[0]+":\\GesObras\\db\\log\\DB_LOG.FDB",usuario,senha);
        }
        catch(ClassNotFoundException Driver)
        {
            JOptionPane.showMessageDialog(null, "Driver nao localizado: "+Driver);
            result = false;
            System.exit(0);
        }
        catch(SQLException Fonte)
        {
            JOptionPane.showMessageDialog(null, "Ocorreu um erro ao conectar ao banco de dados, \n confira se o ip e a porta estao configurados corretamente!");
        }
        return result;
    }

    public void desconecta()
    {
        boolean result = true;
        try
        {
            conexao.close();
            JOptionPane.showConfirmDialog(null, "banco fechado");
        }
        catch(SQLException fecha)
        {
            JOptionPane.showMessageDialog(null, "Nao foi possivel "+
                                          "fechar o banco de dados: "+fecha);
            result = false;
        }

    }
    public void executeSQL(String sql)
    {
        try
        {
            statement = (PreparedStatement) conexao.createStatement(
                       ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);
            resultset = statement.executeQuery(sql);
            //JOptionPane.showMessageDialog(null, "deu certo a pesquisa");
        }
        catch(SQLException sqlex)
        {
         JOptionPane.showMessageDialog(null, "nao foi possivel " +
                 "executar o comando sql,"+sqlex+", o sql passado foi "+sql);
        }
    }
}

mas um erro ocorre qdo tento rodar o programa:

Exception in thread "main" java.lang.ClassCastException: org.firebirdsql.jdbc.FBStatement cannot be cast to java.sql.PreparedStatement
        at db.ConexaoDB.executeSQL(ConexaoDB.java:87)
        at grafica.Splash.Autent(Splash.java:91)
        at grafica.Splash.<init>(Splash.java:38)
        at grafica.Splash.main(Splash.java:87)
Java Result: 1

o que pode ser? valeu

57 Respostas

M

troque
conexao.createStatement
por
conexao.prepareStatement

Z

amigo fiz agora para ver e ta dando erro aki


ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); // erro: cannot find symbol

o que tenho q mudar aki??

valeu

F
  1. Java não é lento.
  2. O q se torna “gargalo de aplicação” é chamada de recursos externos, principalmente remotos, que no seu caso pode ser acesso ao sgdb, arquivos, etc…
  3. Dentro destas chamadas entram detalhes como - arquitetura de implementação das chamadas com boas praticas, banda de rede, tempo de resposta da recurso externo.
    A soma de varias coisas dessa esta deixando seu aplicação lenta.
Z

entao usar o preparedStatement nao resolve?

valeu

M

zicky23:
entao usar o preparedStatement nao resolve?

valeu

nao sei te dizer se o preparedstatement eh mais rapido, mas ele tem varios outros beneficios.

o statement foi a primeira versao e nao deve ser mais usada, so nao eh retirada do java para nao parar projetos existentes.

sobre o seu erro, coloque a exceção toda pra gente ver.

[]'s

F

zicky23:
entao usar o preparedStatement nao resolve?
valeu

Sim…
preparedStatement são 10x mais rápidos que o Statement…uma vez que o comando pode ser pre-compilado e reusado.
Mas não é só isso…

F

zicky23:
entao usar o preparedStatement nao resolve?
valeu

Sim…
preparedStatement são 10x mais rápidos que o Statement…uma vez que o comando pode ser pre-compilado e reusado.
Mas não é só isso…

T

Da uma olhada na quantidade de Strings que vc esta usando na aplicação e se for muito grande pense na possibilidade de substituir por outros tipos.
Ao invés de usar concatenação de strings use stringbuffer por exemplo.

Da uma olhada tbm no banco de dados, na otimização dos selects e do sgbd.

Não sei se é o sei caso, mas se tiver usando DefaultTablemodel com vetores, etc, substitua por um tablemodel próprio.

Realmente o java não é lento, mas a forma de programar faz muita diferença.

Espero ter ajudado.

Z

Vou tentar passar para PrepareStatement… e ver se otimiza

depois vou dar uma analisada sobre os selects…

ahh nao uso o DefaultTableModel… to usando um proprio.

vou ver o que consigo… e posto aki valeu!!!

Z

esqueci de comentar, o server que uso, é um pc normal, e a rede passa por um switch 8 portas, depois chega em um switch 24 portas, para depois ir para a estação. será que isso ajudar na lentidão?

valeu

M

zicky23:
esqueci de comentar, o server que uso, é um pc normal, e a rede passa por um switch 8 portas, depois chega em um switch 24 portas, para depois ir para a estação. será que isso ajudar na lentidão?

valeu

sim, pode. de um exemplo dessa lentidao

Z

assim, no sistema tem um jbuttom que chama um JDialog de solicitações cadastradas, nesse jDialog tem uma JTable que tem que carregar os dados cadastrados cada vez que se abre, então ao clicar nesse jButtom ele demora uns 6 seg para abrir, criei tbm um jTextField de Pesquisa e ao digitar o cód para fazer o filtro tbm fica lento. claro que já tem mais de 1000 itens cadastrados… outra coisa que deveria ser bem rápida mas demora, ao clicar em abrir o sistema demora tbm uns 4 seg para a estação conseguir buscar a conexao com server para autenticar o login…

valeu!!!

M

zicky23:
assim, no sistema tem um jbuttom que chama um JDialog de solicitações cadastradas, nesse jDialog tem uma JTable que tem que carregar os dados cadastrados cada vez que se abre, então ao clicar nesse jButtom ele demora uns 6 seg para abrir, criei tbm um jTextField de Pesquisa e ao digitar o cód para fazer o filtro tbm fica lento. claro que já tem mais de 1000 itens cadastrados… outra coisa que deveria ser bem rápida mas demora, ao clicar em abrir o sistema demora tbm uns 4 seg para a estação conseguir buscar a conexao com server para autenticar o login…

valeu!!!

vc abre a conexao sempre que vai executar essa instruçao? vc usa algum pool de conexoes?

Z

cara, é verdade abro a conexao cada vez que clico para carregar :S… pode ser isso? nao uso nenhum pool… como posso fazer?

M

pode ser sim, abrir a conexao eh uma tarefa um pouco custosa, implemente um pool bem simples que vai melhorar muito ou até resolver seu problema.

M

faça um teste simples, abra a conexao quando vc abrir a sua tela e depois executa as consultas e veja o resultado.

Z

cara e como q faço esse pool? ainda nao pesquisei nada sobre isso.

valeu

M

nao eh uma coisa dificil de implementar, vc vai adiconar uma lib no projeto e criar uma conexao com as classes que o pool te fornecer, existem varias implementacoes de pool, vc q escolhe.
feito isso vc vai pegar a conexao do pool, usar e fechar normalmente. a diferenca eh que o pool nao fecha a conexao ele a mantem de acordo com a necessidade dando um enorme desempenho e seguranca.

Z

blz vou pesquisar na net e fazer uns testes… aviso daki a poko

valeu

Z

ahh, uma pergunta…

em vez de fazer um filtro normal q ao digitar ele vai filtrando os dados na jtable, tem alguma maneira e ja vi em sistemas delphi de ao digitar em um jtextfield apenas ir selecionando a linha ate chegar na desejada…??

valeu

M

zicky23:
ahh, uma pergunta…

em vez de fazer um filtro normal q ao digitar ele vai filtrando os dados na jtable, tem alguma maneira e ja vi em sistemas delphi de ao digitar em um jtextfield apenas ir selecionando a linha ate chegar na desejada…??

valeu

tem sim, mas isso arrebenta com o desempenho da aplicação, a nao ser que vc use algum algoritimo muito inteligente tipo o do google, vc vai ter que dar um select a cada caractere digitado. fica tenso o negocio!!!

S

zicky23

Eu faço isso:

Tenho um jTable preenchido, e coloquei em cima dele um jTextField onde o usuário digita o nome que quer encontrar e o sistema seleciona a primeira linha que encontrar naqueles parâmetros digitados:

Código:

para o JTextField implemento estes dois métodos:

esse pra que caso o usuário digite back space ele apague logo tudo forçando-o a digitar tudo de novo:

private void jTextFieldParteNomeKeyPressed(java.awt.event.KeyEvent evt) {                                               
        if (jTextFieldParteNome.getText() == null) {
            nomeAPesquisar = null;
        }
        if (evt.getKeyCode() == evt.VK_BACK_SPACE) {
            nomeAPesquisar = null;
            jTextFieldParteNome.setText("");
        }// TODO add your handling code here:
    }

e este que faz a busca chamando o método que procura o nome:

private void jTextFieldParteNomeKeyReleased(java.awt.event.KeyEvent evt) {                                                
        if (jTextFieldParteNome.getText().equals("")) {
            nomeAPesquisar = null;
        } else if (nomeAPesquisar == null) {
            nomeAPesquisar = "" + evt.getKeyChar();
        } else {
            nomeAPesquisar = nomeAPesquisar + evt.getKeyChar();
            encontraPedacosDoNomeNaTabela(nomeAPesquisar);
           
        }
    }

O método que encontra o nome é este:

private void encontraPedacosDoNomeNaTabela(String nome) {
        int qtLinhas = modelo.getRowCount();
        int corredor = 0;

        while (corredor < qtLinhas) {
            String nomeNaTabela = ("" + modelo.getValueAt(corredor, 2)); // 2 aqui é a coluna que está o nome que vc deseja localizar
            for (int a = 0; a < nomeNaTabela.length(); ++a) {
         
                if ((nomeNaTabela.substring(0, ++a)).equals(nome.toUpperCase().trim())) {
                    jTableLancamentosFinanceiros.changeSelection(corredor, corredor, false, false);
                    return;
                }
            }
            ++corredor;
        }
    }
S

lembrando que a variável nomeAPesquisar vc declara no escopo da classe como String…

M
SandroSoftwares:
zicky23

Eu faço isso:

Tenho um jTable preenchido, e coloquei em cima dele um jTextField onde o usuário digita o nome que quer encontrar e o sistema seleciona a primeira linha que encontrar naqueles parâmetros digitados:

Código:

para o JTextField implemento estes dois métodos:

esse pra que caso o usuário digite back space ele apague logo tudo forçando-o a digitar tudo de novo:

private void jTextFieldParteNomeKeyPressed(java.awt.event.KeyEvent evt) {                                               
        if (jTextFieldParteNome.getText() == null) {
            nomeAPesquisar = null;
        }
        if (evt.getKeyCode() == evt.VK_BACK_SPACE) {
            nomeAPesquisar = null;
            jTextFieldParteNome.setText("");
        }// TODO add your handling code here:
    }

e este que faz a busca chamando o método que procura o nome:

private void jTextFieldParteNomeKeyReleased(java.awt.event.KeyEvent evt) {                                                
        if (jTextFieldParteNome.getText().equals("")) {
            nomeAPesquisar = null;
        } else if (nomeAPesquisar == null) {
            nomeAPesquisar = "" + evt.getKeyChar();
        } else {
            nomeAPesquisar = nomeAPesquisar + evt.getKeyChar();
            encontraPedacosDoNomeNaTabela(nomeAPesquisar);
           
        }
    }

O método que encontra o nome é este:

private void encontraPedacosDoNomeNaTabela(String nome) {
        int qtLinhas = modelo.getRowCount();
        int corredor = 0;

        while (corredor < qtLinhas) {
            String nomeNaTabela = ("" + modelo.getValueAt(corredor, 2)); // 2 aqui é a coluna que está o nome que vc deseja localizar
            for (int a = 0; a < nomeNaTabela.length(); ++a) {
         
                if ((nomeNaTabela.substring(0, ++a)).equals(nome.toUpperCase().trim())) {
                    jTableLancamentosFinanceiros.changeSelection(corredor, corredor, false, false);
                    return;
                }
            }
            ++corredor;
        }
    }

cara, nao eh desmerecendo seu codigo, ele esta otimo, o problema eh que para fazer isso vc vai precisar esta com os dados do banco todos na jtable, se a tabela for grande vai virar uma lesma aleijada

S

me perdoe mauricioadl

mas entre carregar tudo de vez e fazer a pesquisa e ficar carregando por parte, qual o trabalho mais penoso???

ele vai gastar mais tempo pesquisando por parte do que se baixar logo tudo… eu acho…

Sandro

M

SandroSoftwares:
me perdoe mauricioadl

mas entre carregar tudo de vez e fazer a pesquisa e ficar carregando por parte, qual o trabalho mais penoso???

ele vai gastar mais tempo pesquisando por parte do que se baixar logo tudo… eu acho…

Sandro

isso pensando em tabelas pequenas, mas quando elas crescerem isso vai virar uma tragedia. agora se tiver certeza absoluta q a tabela nao vai crescer, fica perfeito!

Z

na minha aplicacao ta assim:

[img]http://www.vielmond.net/pesquisa-com-filtro.png[/img]

gostaria de uma maneira que ele nao fizesse um select cada vez que eu digitasse uma letra isso ta tornando o sistema mto lento.

como esta no fieldpesquisa:

private void FieldPesquisaKeyReleased(java.awt.event.KeyEvent evt) {                                          
        // TODO add your handling code here:
        if(RContribuinte.isSelected()){
            pesquisa = "WHERE UPPER(C.NOME_CONTRIBUINTE) LIKE '"+FieldPesquisa.getText().toUpperCase()+"%'";
        }else if(RSetor.isSelected()){
            pesquisa = "WHERE UPPER(SE.NOME_SETORES) LIKE '"+FieldPesquisa.getText().toUpperCase()+"%'";
        }else if(RSituacao.isSelected()){
            pesquisa = "WHERE UPPER(SIT.NOME_SITUACOES) LIKE '"+FieldPesquisa.getText().toUpperCase()+"%'";
        }else if(RServico.isSelected()){
            pesquisa = "WHERE UPPER(S.SERVICO) LIKE '"+FieldPesquisa.getText().toUpperCase()+"%'";
        }else if(RCodigo.isSelected()){
            pesquisa = "WHERE S.ID_SOLICITACAO LIKE '"+FieldPesquisa.getText().toUpperCase()+"%'";
        }else if(REndereco.isSelected()){
            pesquisa = "WHERE UPPER(R.NOME_RUAS) LIKE '%"+FieldPesquisa.getText().toUpperCase()+"%'";
        }
        Solicitacoes();
    }

e aqui como q ele seleciona:

public final void Solicitacoes(){

        Object sel,codSolicitacao,nomeContrib,foneContrib,ruaContrib,numeroCasaContrib,bairroContrib,nomeSetor,nomeSituacoes,datahora,servico,justificativa,idsituacao;
        conn.executeSQL("SELECT S.id_solicitacao,S.SEL,C.nome_contribuinte,C.fone,R.nome_ruas,S.numero,B.nome_bairros,SE.nome_setores,SIT.nome_situacoes,SIT.id_situacao,S.data_hora,S.servico,S.justificativa"
                        +" FROM SOLICITACOES S"
                        +" LEFT JOIN CONTRIBUINTE C ON S.id_contribuinte=C.id_contribuinte"
                        +" LEFT JOIN SETORES SE ON S.id_setor=SE.id_setor"
                        +" LEFT JOIN SITUACOES SIT ON S.id_situacao=SIT.id_situacao"
                        +" LEFT JOIN RUAS R ON S.id_rua=R.id_ruas"
                        +" LEFT JOIN BAIRROS B ON C.id_bairros=B.id_bairros "+pesquisa+" ORDER BY S.ID_SOLICITACAO DESC");
        try{
                dados = new ArrayList();
                while (conn.resultset.next()) {

....
S

zicky23

é exatamente sobre isso que discutimos dois tópicos acima!

se vc acha que está demorando, baixa logo todos os dados pro seu jtable e depois disso sim, faz a pesquisa pelo jTextField.

Z

blz, vou usar POOL para fazer a conexao ao abrir o jDialog de pesquisa, ai ql o metodo mais agil para executar esse filtro visto que a tendência é só aumentar os dados que ja ultrapassam 1000 linhas…

valeu

S

agora pelo que estou vendo na sua aplicação vc colocou diversos tipos de pesquisa, logo aqui vc vai ter que alterar:

String nomeNaTabela = ("" + modelo.getValueAt(corredor, 2));

para:

if(jRadioButtonContribuinte.isSelected(){ String nomeNaTabela = ("" + modelo.getValueAt(corredor, 0)); //coluna zero }else if(jRadioButtonTelefone.isSelected(){ String nomeNaTabela = ("" + modelo.getValueAt(corredor, 1)); //coluna um }else if(jRadioButtonEndereco.isSelected(){ String nomeNaTabela = ("" + modelo.getValueAt(corredor, 2)); //coluna dois }else if(jRadioButtonSituacao.isSelected(){ String nomeNaTabela = ("" + modelo.getValueAt(corredor, 4)); //coluna quatro }else if(jRadioButtonCodigo.isSelected(){ String nomeNaTabela = ("" + modelo.getValueAt(corredor, 6)); //coluna seis }

Z

ok, vou tentar

ahh, e tipo assim,

ao abrir o jDialog carregar toda a jtable, e no filtro ao invez de ao digitar ele ir fazendo o filtro nao seria mto mais rápido uma maneira de ele ir apenas selecionando a linha conforme eu ia digitando?

tipo

tenho 10 linhas e ao digitar ele nao apagar as 10 linhas, se ir selecionando uma ate chegar na mais proxima comparacao q eu digitei…

tipo se eu tenho uma linha com um cód: 10021010

ao digitar 1 ele seleciona essa linha, e eu digitar mais o caracter 0 ele continua selecionada na mesma linha, e se eu digitar mais um caracter 1 ai ela “desseleciona” essa linha e vai para proxima q contiver os caracteres 101…

sera q nao seria mais rápido???

S

é justamente isso que o código que eu postei faz!

Ele não apaga linhas da tabela, ele apenas corre a tabela até encontrar algo idêntico com o que você digitou.

Z

ahhhhhhh blz…

vou testar…

te aviso como ficou!

valeu

Z

outra coisa

to com essa conexao pool, mas nao consigo fazer ele achar o driver.

ta rando tudo nao reconhecido no cod abaixo...

a começar por :
static org.firebirdsql.pool.FBWrappingDataSource ds;
package db;

import org.firebirdsql.pool.*;
import org.firebirdsql.*;

static org.firebirdsql.pool.FBWrappingDataSource ds;



public static void setConnectionPool() ///throws Exception
    {
        try
        {
            String maquina = "localhost";
            String user = "SYSDBA";
            String pwd = "masterkey";
            String dir_db = "C:\\dados\\BANCO.FDB";
            String url = "jdbc:firebirdsql:"+maquina+"/3050:"+dir_db+"?lc_ctype=ISO8859_1";
            System.setProperty("FBLog4j", "true");
            ds = new org.firebirdsql.pool.FBWrappingDataSource();
            ds.setDescription("Conexao SiGet");
            ds.setType("type4");
            ds.setSqlRole("USER");
            ds.setEncoding("ISO8859_1");
            ds.setUserName(user);
            ds.setPassword(pwd);
            ds.setLoginTimeout(20);
            ds.setMaxConnections(150);
            ds.setMinConnections(5);
            ds.setNonStandardProperty("isc_dpb_sql_dialect","3");
            ds.setDatabase(maquina+"/3050:"+dir_db);

            /* para gravar em arquivo tudo que ocorrer de erros no JDBC */
            FileOutputStream fos = new FileOutputStream("dados\\jdbclog.txt",true);
            PrintWriter ps = new PrintWriter(fos);
            DriverManager.setLogWriter(ps);
        }
        catch(java.io.IOException jio)
        {}
        catch(java.lang.NoClassDefFoundError nc)
        {
            TG.Mess("Criando o Pool de Conexão",nc.getMessage());
        }
        catch(java.sql.SQLException se)
        {
            TG.Mess("Criando o Pool de Conexão",se.getMessage());
        }
    }

q drive eu tenho q colocar?

M

esse pool do firebird nao funciona mais com as versoes atuais, se vc olhar a documentacao vai ver que esta tudo deprecated.
classe: http://www.jarvana.com/jarvana/view/org/firebirdsql/jdbc/jaybird/2.1.6/jaybird-2.1.6-javadoc.jar!/org/firebirdsql/jdbc/FBWrappingDataSource.html

use o apache DBCP ele eh otimo e simples http://commons.apache.org/dbcp/

BasicDataSource ds = new BasicDataSource(); ds.setDriverClassName("driver_do_seu_banco"); ds.setUsername("usuario"); ds.setPassword("senha"); ds.setUrl("url"); ds.getConnection();

[]'s

Z

só uma dúvida, esse código para fazer a selecao ao invez de filtro, nao funciona se o valor for número?

ta travando meu sistema qdo digito um número para pesquisa por código.

Z

infelizmente nao funcionando como desejado

código:

private void encontraPedacosDoNomeNaTabela(String nome) {
         int qtLinhas = TablePesquisa.getRowCount();  
         int corredor = 0;
         String nomeNaTabela = null;

         while (corredor < qtLinhas) {  
             if(RContribuinte.isSelected()){
                if(RContribuinte.isSelected()){
                nomeNaTabela = (TablePesquisa.getValueAt(corredor, 0).toString()); //coluna zero
                }else if(RSetor.isSelected()){
                nomeNaTabela = (TablePesquisa.getValueAt(corredor, 2).toString()); //coluna um
                }else if(RSituacao.isSelected()){
                nomeNaTabela = (TablePesquisa.getValueAt(corredor, 3).toString()); //coluna dois
                }else if(RServico.isSelected()){
                nomeNaTabela = (TablePesquisa.getValueAt(corredor, 5).toString()); //coluna quatro
                }else if(RCodigo.isSelected()){
                nomeNaTabela = (TablePesquisa.getValueAt(corredor, 6).toString()); //coluna seis
                }else if(REndereco.isSelected()){
                nomeNaTabela = (TablePesquisa.getValueAt(corredor, 4).toString()); //coluna 4
                }
             for (int a = 0; a < nomeNaTabela.length(); ++a) {

                 if ((nomeNaTabela.substring(0, ++a)).equals(nome.toUpperCase().trim())) {
                     TablePesquisa.changeSelection(corredor, corredor, false, false);  
                     return;  
                 }  
             }  
             ++corredor;  
         }  
     }
    }
private void FieldPesquisaKeyPressed(java.awt.event.KeyEvent evt) {
        // TODO add your handling code here:
       if (FieldPesquisa.getText() == null) {
           nomeAPesquisar = null;
       }
       if (evt.getKeyCode() == evt.VK_BACK_SPACE) {
           nomeAPesquisar = null;
           FieldPesquisa.setText("");
       }
    }
private void FieldPesquisaKeyReleased(java.awt.event.KeyEvent evt) {                                          
        // TODO add your handling code here:

       if (FieldPesquisa.getText().equals("")) {
           nomeAPesquisar = null;
       } else if (nomeAPesquisar == null) {
           nomeAPesquisar = "" + evt.getKeyChar();
       } else {
           nomeAPesquisar = nomeAPesquisar + evt.getKeyChar();
           encontraPedacosDoNomeNaTabela(nomeAPesquisar);

       }
        //Solicitacoes();
    }

o que acontece:

ele seleciona depois da terceira letra digitada se nao tiver acento, se tiver ele nao acha. na busca por código ele trava logo que digito o segundo caracter numerico.

o que deveria acontecer:

a cada letra ou numero digitado ele deveria selecionar a linha mais proxima q contiver a string digitada....

se alguem souber como arrumo esse código posta ai

valeu!!

Z

bom dia pessoal ainda estou na busca para essa solucao se alguem tiver alguma sugestao.

obrigado

E

zicky23:
bom dia pessoal ainda estou na busca para essa solucao se alguem tiver alguma sugestao.

obrigado

Olá, Zicky!

Eu vi que vc postou ali atrás que vc faz um select a cada letra que a pessoa digita. Isso realmente vai deixar sua aplicação muito lenta, porque neste caso, se tiverem 5 pessoas digitando 5 letras cada, serão 25 selects no banco de dados de uma vez só. Sem falar ainda na rede, que não aguentaria todas informações de uma vez.

Uma vez eu precisei fazer isso, e eu fiz da seguinte maneira: Quando a janela abre, eu faço um SELECT * pra puxar todos os dados e os coloco num ArrayList. Quando o cara digita a letra eu faço uma pesquisa no ArrayList e não no Banco.

Tenta fazer isso, que vai resolver seu problema.

Z

hummm… isso seria minha solução, vc tem algum exemplo ai pra me passar?

obrigado

E
zicky23:
hummm... isso seria minha solução, vc tem algum exemplo ai pra me passar?

obrigado

Estou num computador sem compilador Java agora, então me perdoe por eventuais erros de sintaxe...

Eu fiz mais ou menos assim: Se eu tenho uma tabela de produtos no banco, com os campos id e nome do produto. Eu faria um select de todos os campos ordenado por nome: SELECT id, nome FROM produto ORDER BY nome ASC; Nesse caso, fica mais fácil de vc jogar esses dados num ArrayList se vc tiver uma classe Produto, ex.:
public class Produto {
    
    private int id;
    private String nome;

    public Produto(int id, String nome) {
        this.id = id;
        this.nome = nome;
    }

    //Getters e setters aqui

}
Daí vc jogaria esses dados no arraylist, assim que a janela fosse aberta:
//seria algo parecido com isso
ResultSet rs = statement.executeQuery("SELECT id, nome FROM produto ORDER BY nome ASC;");
List<Produto> lista = new ArrayList<Produto>();
while (rs.next()) {
    int id = rs.getInt("id");
    String nome = rs.getString("nome");
    Produto prod = new Produto(id, nome);
    list.add(prod);
}
E no evento onKeyPress do campo de pesquisa, vc faz algo parecido com isso:
String pesquisa = pesquisaTextField.getText();
List<Produto> resultados = new ArrayList<Produto>();
for (Produto p : lista) {
    if (p.getNome().startsWith(pesquisa)) {
        resultados.add(p);
    }
}

Daí vc vai publicando esses resultados na sua tabela.
Dá uma olhada se não dá pra fazer melhor que isso, porque eu inventei isso agora e eu tou sem compilador pra testa.

Espero ter ajudado!

Z

Valeu mesmo, com essa explicação já tenho uma base, vou começar a fazer e vou postando aki

obrigado mesmo

ate+

Z

bom dia fiz da seguinte forma:

AbstractModelServico.java

package model;

import javax.swing.table.AbstractTableModel;
import java.util.List;
import java.util.ArrayList;
import javax.swing.table.TableModel;
import java.util.Collections;

class  ServicoTableModel extends AbstractTableModel {


    private static final int COL_NOME = 0;
    private static final int COL_FONE = 1;
    private static final int COL_RUA = 2;
    private static final int COL_NUM = 3;
    private static final int COL_SITUACAO = 4;
    private static final int COL_BAIXAR = 5;
    private static final int COL_COD = 6;

    private List<Servicos> lista;



    public ServicoTableModel(List<Servicos> lista) {

        this.lista = lista;

    }

    public int getRowCount() {

        return lista.size();
    }

    public int getColumnCount() {

        return 7;
    }

    public String getColumnName(int column) {

        if (column == COL_NOME) return "NOME";
        if (column == COL_FONE) return "FONE";
        if (column == COL_RUA) return "RUA";
        if (column == COL_NUM) return "Nº";
        if (column == COL_SITUACAO) return "SITUACAO";
        if (column == COL_BAIXAR) return "BAIXAR";
        if (column == COL_COD) return "COD";
        return ""; //Nunca deve ocorrer
    }

    public Object getValueAt(int row, int column) {

        Servicos titulo = lista.get(row);
        if (column == COL_NOME) return titulo.getNomeContrib();
        else if (column == COL_FONE) return titulo.getFoneContrib();
        else if (column == COL_RUA) return titulo.getRuaContrib();
        else if (column == COL_NUM) return titulo.getNumeroCasaContrib();
        else if (column == COL_SITUACAO) return titulo.getNomeSituacoes();
        else if (column == COL_BAIXAR) return titulo.getSel();
        else if (column == COL_COD) return titulo.getCodSolicitacao();
        throw new IllegalArgumentException("Invalid column");
        //return ""; //Nunca deve ocorrer

    }

    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {

        Servicos titulo = lista.get(rowIndex);
        if (columnIndex== COL_NOME) titulo.setNomeContrib(aValue.toString());
        else if (columnIndex== COL_FONE) titulo.setFoneContrib(aValue.toString());
        else if (columnIndex== COL_RUA) titulo.setRuaContrib(aValue.toString());
        else if (columnIndex== COL_NUM) titulo.setNumeroContrib((Integer)aValue);
        else if (columnIndex== COL_SITUACAO) titulo.setNomeSituacoes(aValue.toString());
        else if (columnIndex== COL_BAIXAR) titulo.setSel((Boolean)aValue);
        else if (columnIndex== COL_COD) titulo.setCodSolicitacao((Integer)aValue);

    }


    public Class<?> getColumnClass(int columnIndex) {

        if (columnIndex == COL_NOME) {
            return String.class;
        } else if (columnIndex == COL_FONE) {
            return String.class;
        } else if (columnIndex == COL_RUA) {
            return String.class;
        } else if (columnIndex == COL_NUM) {
            return String.class;
        } else if (columnIndex == COL_SITUACAO) {
            return String.class;
        } else if (columnIndex == COL_BAIXAR) {
            return String.class;
        } else if (columnIndex == COL_COD) {
            return String.class;
        } else {

            return String.class;
        }
    }


    public Servicos get(int row) {

        return lista.get(row);
    }
}

aqui ta a classe Servicos

package model;

import java.util.ArrayList;


public class Servicos {
    java.sql.Timestamp datahora;
    boolean sel;
    private int numeroCasaContrib,codSolicitacao,idsituacao;
    private String nomeContrib,nomeSetor,foneContrib,ruaContrib,nomeSituacoes,bairroContrib,servico,justificativa;
    private ArrayList linhas = null;
    private String[] colunas = null;

    public Servicos(
            String nomeContrib,
            String foneContrib,
            String ruaContrib,
            int numeroCasaContrib,
            String nomeSituacoes,
            boolean sel,
            int codSolicitacao,
            String nomeSetor,
            String bairroContrib,
            java.sql.Timestamp datahora,
            String servico,
            String justificativa,
            int idsituacao
            ) {
        this.nomeContrib = nomeContrib;
        this.foneContrib = foneContrib;
        this.ruaContrib = ruaContrib;
        this.numeroCasaContrib = numeroCasaContrib;
        this.nomeSituacoes = nomeSituacoes;
        this.sel = sel;
        this.codSolicitacao = codSolicitacao;
        this.nomeSetor = nomeSetor;
        this.bairroContrib = bairroContrib;
        this.datahora = datahora;
        this.servico = servico;
        this.justificativa = justificativa;
        this.idsituacao = idsituacao;
    }

    //nome get and set
    public String getNomeContrib() {
        return this.nomeContrib;
    }
    public void setNomeContrib(String NomeContrib) {
        this.nomeContrib = NomeContrib;
    }

    //fone get and set
    public String getFoneContrib() {
        return this.foneContrib;
    }
    public void setFoneContrib(String FoneContrib) {
        this.foneContrib = FoneContrib;
    }

    //rua get and set
    public String getRuaContrib() {
        return this.ruaContrib;
    }
    public void setRuaContrib(String RuaContrib) {
        this.ruaContrib = RuaContrib;
    }

    //numero casa get and set
    public int getNumeroCasaContrib() {
        return this.numeroCasaContrib;
    }
    public void setNumeroContrib(int NumeroCasaContrib) {
        this.numeroCasaContrib = NumeroCasaContrib;
    }

    //fone get and set
    public String getNomeSituacoes() {
        return this.nomeSituacoes;
    }
    public void setNomeSituacoes(String NomeSituacoes) {
        this.nomeSituacoes = NomeSituacoes;
    }

    //fone get and set
    public boolean getSel() {
        return this.sel;
    }
    public void setSel(boolean Sel) {
        this.sel = Sel;
    }

    //fone get and set
    public int getCodSolicitacao() {
        return this.codSolicitacao;
    }
    public void setCodSolicitacao(int CodSolicitacao) {
        this.codSolicitacao = CodSolicitacao;
    }

    //fone get and set
    public String getNomeSetor() {
        return this.nomeSetor;
    }
    public void setNomeSetor(String NomeSetor) {
        this.nomeSetor = NomeSetor;
    }

    //fone get and set
    public String getBairroContrib() {
        return this.bairroContrib;
    }
    public void setBairroContrib(String BairroContrib) {
        this.bairroContrib = BairroContrib;
    }

    //fone get and set
    public java.sql.Timestamp getDataHora() {
        return this.datahora;
    }
    public void setDataHora(java.sql.Timestamp DataHora) {
        this.datahora = DataHora;
    }

    //fone get and set
    public String getServico() {
        return this.servico;
    }
    public void setServico(String Servico) {
        this.servico = Servico;
    }

    //fone get and set
    public String getJustificativa() {
        return this.justificativa;
    }
    public void setJustifivatica(String Justificativa) {
        this.justificativa = Justificativa;
    }

    //fone get and set
    public int getIdSituacao() {
        return this.idsituacao;
    }
    public void setIdSituacao(int IdSituacao) {
        this.idsituacao = IdSituacao;
    }
}

aqui ta a TableModel2

package model;

import java.util.ArrayList;
import java.util.Iterator;
import javax.swing.table.AbstractTableModel;

public class TableModel2 extends AbstractTableModel{


    private ArrayList linhas = null;
    private String [] colunas = null;
    private boolean [] colsEdicao;

    public TableModel2(ArrayList dados, String[] colunas, boolean [] edicao){
            setLinhas(dados);
            setColunas(colunas);
            colsEdicao = edicao;
    }

    public int getColumnCount() {return getColunas().length;}

    public int getRowCount() {return getLinhas().size();}

    public Object getValueAt(int rowIndex, int columnIndex) {
        // Obtem a linha, que é uma String []
        String [] linha = (String [])getLinhas().get(rowIndex);
        // Retorna o objeto que esta na coluna
        return linha[columnIndex];
    }

        public String[] getLinha(int row)
        {
            String [] linha = (String[])getLinhas().get(row);
            return linha;
        }

    public String[] getColunas() {return colunas;}
    public ArrayList getLinhas() {return linhas;}
    public void setColunas(String[] strings) {colunas = strings;}
    public void setLinhas(ArrayList list) {linhas = list;}

    public void setValueAt(Object value, int row, int col){
        // Obtem a linha, que é uma String []
        String [] linha = (String [])getLinhas().get(row);
        // Altera o conteudo no indice da coluna passado
        linha[col] = (String)value;
        // dispara o evento de celula alterada
        fireTableCellUpdated(row,col);
    }

    public boolean isCellEditable(int row, int col){
        return colsEdicao[col];
    }

    public void addRow( String [] dadosLinha){
        getLinhas().add(dadosLinha);
        // Informa a jtable de que houve linhas incluidas no modelo
        // COmo adicionamos no final, pegamos o tamanho total do modelo
        // menos 1 para obter a linha incluida.
        int linha = getLinhas().size()-1;
        fireTableRowsInserted(linha,linha);
        return;
    }

    public void removeRow(int row){
        getLinhas().remove(0);
        // informa a jtable que houve dados deletados passando a
        // linha removida
        fireTableRowsDeleted(row,row);
    }

    public boolean removeRow(String val, int col){
        // obtem o iterator
        Iterator i = getLinhas().iterator();
        int linha = 0;
        // Faz um looping em cima das linhas
        while(i.hasNext()){
            // Obtem as colunas da linha atual
            String[] linhaCorrente = (String[])i.next();
            linha++;
            // compara o conteudo String da linha atual na coluna desejada
            // com o valor informado
            if( linhaCorrente[col].equals(val) ){
                getLinhas().remove(linha);
                // informa a jtable que houve dados deletados passando a
                // linha removida
                fireTableRowsDeleted(linha,linha);
                return true;
            }
        }
        // Nao encontrou nada
        return false;
    }

    public String getColumnName(int col){
        return getColunas()[col];
    }

}

aqui ta parte da PesquisaSolicitacao como estou chamando para mostrar a table.

public class PesquisarSolicitacao extends javax.swing.JDialog {

    String pesquisa = "",nomeAPesquisar;
    private NovoServico parent;
    private TableRowSorter<TableModel> sorter;
    ServicoTableModel model;

        //novo 26/04/2012
        final ServicoDao lista = new ServicoDao();
        List<Servicos> lista2 = lista.ServicoDao();

//...

        model = new ServicoTableModel(lista2);
        TablePesquisa.setModel(model);
        TablePesquisa.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
//...


//aki quero q cada vez que eu digitar uma letra gostaria que fosse selecionando uma linha, mas não ta funcionando.

    private void FieldPesquisaKeyReleased(java.awt.event.KeyEvent evt) {                                          
        // TODO add your handling code here:

        String pesquisa = FieldPesquisa.getText();
        List<Servicos> resultados = new ArrayList<Servicos>();
        for (Servicos p : lista2) {
            if (p.getNomeContrib().startsWith(pesquisa)) {
                resultados.add(p);
            }
        }
}

ALGUEM PODE ME DAR UMA AJUDINHA??

valeu

E

Qual é sua dúvida?

Z

consegui carregar os dados na ArrayList e mostrar na jtable, só que nao consigo fazer a pesquisa pelo jTextField,

nao tá funcionando, qdo digito nao acontece nada.

//aki quero q cada vez que eu digitar uma letra gostaria que fosse selecionando uma linha, mas não ta funcionando.  
  
    private void FieldPesquisaKeyReleased(java.awt.event.KeyEvent evt) {                                            
        // TODO add your handling code here:  
  
        String pesquisa = FieldPesquisa.getText();  
        List<Servicos> resultados = new ArrayList<Servicos>();  
        for (Servicos p : lista2) {  
            if (p.getNomeContrib().startsWith(pesquisa)) {  
                resultados.add(p);  
            }  
        }  
}
Z

Tentei dessa maneira mas nada tbm

private void FieldPesquisaKeyReleased(java.awt.event.KeyEvent evt) {                                          
        // TODO add your handling code here:

        ArrayList resultado = new ArrayList();

        for (Iterator iter = lista2.iterator(); iter.hasNext();) {
            Servicos s1 = (Servicos) iter.next();
            if (s1.getNomeContrib().equals(s1.getNomeContrib())) {
                resultado.add(s1);
            }
           }
}
E

Você tem que aplicar esses resultados na tabela.

Z

e como faço para aplicar, desculpa realmente estou um pouco perdido. :slight_smile:

valeu

E
zicky23:
consegui carregar os dados na ArrayList e mostrar na jtable, só que nao consigo fazer a pesquisa pelo jTextField,

nao tá funcionando, qdo digito nao acontece nada.

//aki quero q cada vez que eu digitar uma letra gostaria que fosse selecionando uma linha, mas não ta funcionando.  
  
    private void FieldPesquisaKeyReleased(java.awt.event.KeyEvent evt) {                                            
        // TODO add your handling code here:  
  
        String pesquisa = FieldPesquisa.getText();  
        List<Servicos> resultados = new ArrayList<Servicos>();  
        for (Servicos p : lista2) {  
            if (p.getNomeContrib().startsWith(pesquisa)) {  
                resultados.add(p);  
            }  
        }  
}

Nesse código vc só está colocando os resultados da pesquisa num List.
Eu não vi vc limpando a sua JTable e colocando os resultados na JTable.

Z

humm, ta vou tentar… \o

valeu

Z

tentei assim mas nada =/

String pesq = FieldPesquisa.getText(); List<Servicos> resultados = new ArrayList<Servicos>(); for (Servicos p : lista2) { if (p.getNomeContrib().startsWith(pesq)) { resultados.add(p); } model = new ServicoTableModel(resultados); }

da mais uma dica ai :smiley:

valeu

E

Estava vendo o seu código, e agora seu problema está na sua classe ServicoTableModel.

Sempre quando vc altera um dado no tableModel, vc tem que chamar o método fireTableDataChanged(); pra avisar a JTable que os dados foram alterados.

Recriar o objeto ServicoTableModel não resolve. Vc precisa adicionar essa lista ao seu TableModel.

Vai na sua classe ServicoTableModel e coloca esse método:

public void addAll(Collection&lt;Servico&gt; coll) {
		for (Servico s : coll) {
			coll.add(s);
		}
		fireTableDataChanged();
	}
Z

adicionei já la na ServicoTableModel, mas ainda nao consegui resolver o grande problema “pra mim”…

vou continuar tentando…

valeu

Z

continuo na luta aki… mas nao consigo encontrar nada parecido aki no forum…

String pesq = FieldPesquisa.getText(); List<Servicos> resultados = new ArrayList<Servicos>(); for (Servicos p : lista2) { if (p.getNomeContrib().startsWith(pesq)) { System.out.println (p.getNomeContrib()); //nova pesquisa //resultados.add(p); model = new ServicoTableModel(lista2); TablePesquisa.setModel(model); } }

tentei dessa maneira porém, só funciona pelo out.println. na table só muda na primeira letra e nao acontece mais nada…

alguém pode me dar uma ajuda?

Z

fiz da seguinte forma e funcionou, gostaria de uma opinião, ta correto dessa maneira q eu fiz? ou devo continuar la no keyreleased do FieldPesquisa??

FieldPesquisa.getDocument().addDocumentListener( new DocumentListener() { public void changedUpdate(DocumentEvent e) { newFilter(); } public void insertUpdate(DocumentEvent e) { newFilter(); } public void removeUpdate(DocumentEvent e) { newFilter(); } });

private void newFilter() { RowFilter rf = null; //If current expression doesn't parse, don't update. try { rf = RowFilter.regexFilter(FieldPesquisa.getText(), 0); } catch (java.util.regex.PatternSyntaxException e) { return; } sorter.setRowFilter(rf); }

o exemplo que usei para aplicar foi daqui:
http://docs.oracle.com/javase/tutorial/displayCode.html?code=http://docs.oracle.com/javase/tutorial/uiswing/examples/components/TableFilterDemoProject/src/components/TableFilterDemo.java

F

Essa lentidao (bem como estouros de memoria) é comum principalmente em Sistemas com vazamento de memória.
Existem MUITAS técnicas pra se impedir isso.
Ou em situações onde vc joga pro seu cliente umonte de coisa que ele nem sequer vai usar.

Ex: Vc tem um grid de resultados de uma pesquisa. Ai vc traz 10.000 registros pra esse grid.
Vamos pensar… seu usuario vai “navegar” em 10.000 registros? DUVIDO muito. Nem em 1000.
Entao pq TRAZER 10.000 registros? Se a consulta for retornar mais de 100 resultados (vc sabe isso com counts), peça-o gentilmente para “refinar” a pesquisa fornecendo mais parâmetros.

Isso torna a aplicação RAPIDA e economiza um bocado de recurso.

Em aplicações front-end pra Banco de Dados, os gargalos mais comum costumam ser CONSULTAS MAL FEITAS e má gerencia desses resultados no Java.
Bem como pool de conexoes mal trabalhado.

Z

mas o problema é que o usuário pode usar qlqr registro, pois todos os dias o usuário busca determinado registro para “dar baixa”, a pergunta é, se eu limitar esses registros para digamos 100, na hora que eu fazer a busca no FieldPesquisa os que nao aparecem vão aparecer?

valeuuuu

Criado 28 de fevereiro de 2012
Ultima resposta 3 de mai. de 2012
Respostas 57
Participantes 7