Dica para fazer uma Thread com duas tabelas relacionadas e atualizá-las Java Swing

6 respostas
N

Pessoal bom dia,

[b]Estou com duvidas sobre como fazer dois loops para percorrer duas tabelas relacionadas quando iniciar o programa. Fiz uma thread que copiei da ideia do Vini e já está executando no inicio do programa, a minha duvida é:

  1. Necessito fazer isso no inicio da execução do programa na tela de login?
  2. Não sei como a Thread vai se comportar durante a execução de um cadastro ou consulta ou o tempo que o programa vai ficar parado ou rodando?
  3. Como fazer a leitura das duas tabelas relacionadas e atualização dos dias uteis numa das tabelas no meu Dao?(Não sei se é a melhor maneira é com arraylist, iterator ou while?
  4. Essas tabelas devem conter mais ou menos uma proporção de 10 e 100.000 registros(pai e filho).
    Necessito de uma ideia e exemplos prático de como fazer esses loops quando iniciar o programa. Este trabalho é com java swing, e se alguem tiver alguma ideia, por favor, preciso de ajuda para resolver da melhor forma possivel.
    Agradeço a todos.[/b]

6 Respostas

N

Olá pessoal
[b]Vou tentar explicar melhor a minha duvida e talvez com o codigo postado abixo esclareça mais.
O objetivo dessa Thread é fazer o calculo de dias uteis de todos os registros do modelo (FaseExecucao), atraves da data de recepção até a data de hoje. Para isso preciso fazer uma consulta na tabela Fichas e verificar a sua situação de não concluidas. Tenho uma ficha para muitas fases.
Este processo já está executando quando inicio a tela de login do sistema. Tenho basicamente tres duvidas em relação a essa Thread:

  1. Sou iniciante no java e preciso entender o processo de loops, será qua a maneira que fiz no codigo abaixo é a maneira correta?, depois com a continução não vai dar algum problema de segurança? preciso ler as duas tabelas. Senão queria um exemplo de como fazer esse dois loops. Como Podemos fazer atualizações na base de dados de Fichas apartir dessas consultas, para essa Thread? . Os loops que fiz parece que está funcionando, mas para verificar se está, preciso atualizar os dias uteis calculados e gravados na tabela de fichas, no campo dias. quando vou atualizar os dias úteis calculados ele me da a mensagem do catch na gravaçao
  2. Este é um sistema cliente x servidor(MVC). Segundo o pattern Dao para atualizar uma base de dados, preciso editar todos os campos da base e depois dar um update na tabela Fichas conforme o codigo abaixo. O meu problema parece que só são esses.
    3)Se o usuario reiniciar o sistema ou sair do sistema se não estiver acabado esse processo existe uma maneira de prosseguir de onde parou quando ele entrar novamente?
    [/b]
public class MyThread extends JFrame{
        // Local onde atualizaremos a hora  
        private JLabel lblHora;  
        private Date recepcao;

        private Integer IdCor = 0;
        private Integer IdFabricante = 0;
        private Integer IdProtese = 0;
        private Integer IdTipodePreco = 0;
        private Integer IdPreco = 0;
        private Integer IdFormadePagamento = 0;
        private String jTextAreaObs = null;
        private String prova = null;
        private Date jfdchegada = null;
        private Date jFdPrevisaoEntrega = null;
        private Double Qtdeprot = 0.0;
        private String spreco = null;
        String Preco = null;
        private int IdOs = 0;
        private int IdFicha = 0;

        ConvData            convdata            = new ConvData();
        Feriado f = new Feriado();
        Fichas ficha = new Fichas();
        FaseExecucao fase = new FaseExecucao();
        private ArrayList<FaseExecucao> listaFaseExecucao = new ArrayList<FaseExecucao>();
        private ArrayList<Feriado> listaFeriado = new ArrayList<Feriado>();
        private ArrayList<Fichas> listaFichas = new ArrayList<Fichas>();
        Date datahoje = null;
        // Formatador da hora  
        private static final DateFormat FORMATO = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
        private Double valor;
        Dao<Fichas> daoFicha = null;
        private Integer diasUteis;
      
        public MyThread() {  
            // Construímos nosso frame  
            super("Exemplo de Thread Horas");  
//            setLayout(new FlowLayout());  
            getContentPane().add(getLblHora()); 
            
//            datahoje.setTime(getLblHora());  
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
            setSize(200, 75);  
            setVisible(true);  
      
            // Iniciamos a thread do relógio. Tornei uma deamon thread para que seja  
            // automaticamente finalizada caso a aplicação feche.  
            Thread clockThread = new Thread(new ClockRunnable(), "Clock thread");  
            clockThread.setDaemon(true);  
            clockThread.start();
            atualizarFaseExecucaoRecepcao();
        }  
      
        private JLabel getLblHora() {  
            if (lblHora == null) {  
                lblHora = new JLabel(); 
            }  
            return lblHora;  
        }  
      
        /** 
         * Método para atualizar a hora no formulário. Não é thread-safe, portanto, 
         * se o utilizado fora da thread da AWT, deve-se utilizar um dos comandos da 
         * EventQueue (invokeLater ou invokeAndWait). 
         */  
        public void setHora(Date date) {  
            getLblHora().setText(FORMATO.format(date));  
        }

       /** 
         * Runnable que contém o código que atuará na nossa thread. Basicamente, ele 
         * chama o método setHora de segundo em segundo, passando a data atual. 
         */  
        private class ClockRunnable implements Runnable {  
            public void run() {  
                try {  
                    while (true) {  
                        // Aqui chamamos o setHora através da EventQueue da AWT.  
                        // Conforme dito, isso garante Thread safety para o Swing.  
                        EventQueue.invokeLater(new Runnable() {  
                            public void run() {  
                                // Só podemos chamar setHora diretamente dessa  
                                // forma, pois esse Runnable é uma InnerClass não  
                                // estática.  
                                setHora(new Date());  
                            }  
                        });  
                        // Fazemos nossa thread dormir por um segundo, liberando o  
                        // processador para outras threads processarem.  
                        Thread.sleep(1000);  
                    }  
                }  
                catch (InterruptedException e) {  
                }  
            }  
        }  
//Aqui começa a atualização das tabelas de Fichas de clientes e Fase de Execução.
 
    private void atualizarFaseExecucaoRecepcao() {
//        System.out.println("passou em atualiza FaseExecucao!");  
        Date dataHoje = new Date();
//        System.out.println("passou dataHoje="+dataHoje); 
        int identificador = 0;
        int diasUteis = 0;
// Percorrer atraves de um laço os registros de fichas de clientes
// preciso ler cada registro na base de dados do Postgres e executar cada registro de fichas.        
        try {
            daoFicha = new FichasDao();
            listaFichas = (ArrayList<Fichas>) daoFicha.findbyname("CONCLUIDA");
            for (Iterator iterator = listaFichas.iterator(); iterator.hasNext(); ) {    
                Fichas ficha = (Fichas) iterator.next();    
                   //faz verificação se for o caso.
                  if(iterator != null){  
                    IdOs = ficha.getIdos();
                    IdFicha = ficha.getId();
                    IdCor = ficha.getIdcor();
                    IdFabricante = ficha.getIdfabricante();
                    IdProtese = ficha.getIdprotese();
                    IdTipodePreco = ficha.getIdtipopreco();
                    IdPreco = ficha.getIdpreco();
                    IdFormadePagamento = ficha.getIdformadepagamento();
                    jTextAreaObs = ficha.getObservacao();
                    prova = ficha.getProva();
                    jfdchegada = ficha.getChegada();
                    jFdPrevisaoEntrega = ficha.getVencendo();
                    Qtdeprot = ficha.getPreco();
                    Preco = (String.valueOf(ficha.getPreco()));
         System.out.println("situacao="+ficha.getSituacao()+" idos="+ficha.getIdos().toString()+"+ ficha="+ficha.getId().toString());
// Percorrer atraves de outro laço os registros de fase de execução de clientes
// preciso ler cada registro na base de dados do Postgres e executar cada registro de fase pela data de recepção.        
                    FaseExecucaoDao dao = null;
                    try {
                        dao = new FaseExecucaoDao();
                        listaFaseExecucao = (ArrayList<FaseExecucao>)(dao.findbyfiltrochaves(IdOs, IdFicha, identificador)); 
            //        System.out.println("passou atualizarsituacao");
                        Iterator<FaseExecucao> it = listaFaseExecucao.iterator();  
  
                           //Enquanto temos fase de execucao  
                        while (it.hasNext()) {  
                            //faz verificação se for o caso.  
                                if (it != null){
                                FaseExecucao fas = (FaseExecucao)it.next();
                                if(fas.getIdos().equals(IdOs) && (fas.getIdficha().equals(IdFicha))){
                                   recepcao = fas.getRecepcao();
                                   Long dias = ConvData.nDias(recepcao);
                                   Calendar cal = Calendar.getInstance();  
                                   cal.setTime(recepcao);
                                   cal.add(Calendar.DAY_OF_MONTH, 1);  
                                   recepcao = (java.util.Date)(cal.getTime());  
//                    System.out.println("Data Chegada ="+recepcao+" os="+fas.getIdos().toString()+" ficha="+fas.getIdficha().toString()+" id="+fas.getId().toString());
//                    System.out.println("Numero de Dias ="+dias);
                                    diasUteis = 0;
                                    for (int i = 0; i < dias; i++) { 
                                        Date dataAgenda = (ConvData.adicionarDiasUteis(recepcao, Integer.valueOf(dias.toString())));  
                                        java.util.Date d = new java.util.Date(dataAgenda.getTime());  
                                        String s = new SimpleDateFormat("dd/MM/yyyy").format(d);  
            //                            System.out.println("Data Agenda ="+dataAgenda + " data transformada date="+d +" data string ="+s);
//             metodo para validar se o dia considerado util é feriado ou não, atraves da consulta da tabela de feriados do estado.                  
                                        boolean feriado = validarDiaUtil(d);
                                        if (!feriado){
                                            diasUteis++;
                                            int resultData = (ConvData.comparaData(d,dataHoje));
                                            if((resultData == 0) ||(resultData > 0)){
                                                i=(Integer.valueOf(dias.toString()));
//            metodo para gravar a quantidade de dias uteis na ficha do cliente
                                                   gravarDiasUteis();
//                    System.out.println("passou em gravaDiasUteis ="+diasUteis);
                                                    }
//                    System.out.println("diasUteis ="+diasUteis);
                                        }
                                        cal.setTime(d);
                                        cal.add(Calendar.DAY_OF_MONTH, 1);  
                                        recepcao = (java.util.Date)(cal.getTime());  
                                        String str = new SimpleDateFormat("dd/MM/yyyy").format(recepcao);  

 //                                       System.out.println("Data recepcao + 1 ="+recepcao+" recepcao string ="+str);
                                    }  
 //                                   System.out.println("Dias uteis="+diasUteis);
 //            bypassa ficha ou sai do loop
                                }else{
                                     JOptionPane.showMessageDialog(null, "ERRO. Fase de Execução Vazia!(MyTread)");
                                     return;
                                }
//                            }
                        }      
                    } catch (SQLException e) {
                        Logger.getLogger(jIFOs.class.getName()).log(Level.SEVERE, null, e);
                    } // até aqui fase de execucao
// aqui é a ficha
                  } 
//               }
                else{
                     JOptionPane.showMessageDialog(null, "ERRO. Ficha de ordem de serviço Vazia!(MyTread)");
                     return;
               }
            }
        } catch (SQLException ex) {
            Logger.getLogger(jIFOs.class.getName()).log(Level.SEVERE, null, ex);
               System.out.println("1. catch exception");
        }
        try {
            daoFicha.closeConnection();
        } catch (SQLException e) {
            Logger.getLogger(jIFOs.class.getName()).log(Level.SEVERE, null, e);
               System.out.println("2. catch exception");
        }
        
                    
    }

    private boolean validarDiaUtil(Date data) {
        boolean feriado = false;
        Dao<Feriado> dao = null;
        try {
            dao = new FeriadoDao();
            listaFeriado = (ArrayList<Feriado>) dao.listAll();
            for (Feriado fs1 : listaFeriado) {
               if(fs1 instanceof Feriado){  
                       //aqui é feito um cast  
                    Feriado fer = (Feriado)fs1;  
                   //faz verificação se for o caso.
                    if (listaFeriado != null){
                        if((fer.getDataferiado().equals(data))){  
//               System.out.println("passou no if validarDiaUtil= true"+fer.getDataferiado().toString() );
                             feriado = true;
                        }else{
//               System.out.println("passou no else validarDiaUtil= false"+fer.getDataferiado().toString());
                             feriado = false;  
                        }
                    }else{
                        JOptionPane.showMessageDialog(null, "Erro! Lista de Feriados Vazia!!!");
                    }
               }else{
                        JOptionPane.showMessageDialog(null, "Erro! Lista de Feriados Vazia!!!");
                    }
            }
        } catch (SQLException ex) {
            Logger.getLogger(jIFOs.class.getName()).log(Level.SEVERE, null, ex);
        }
        try {
            dao.closeConnection();
        } catch (SQLException e) {
            Logger.getLogger(jIFOs.class.getName()).log(Level.SEVERE, null, e);
        }
        return feriado;
        
    }

    private void editaCamposOsFichas() {
        ficha.setIdcor(IdCor);
        ficha.setIdfabricante(IdFabricante);
        ficha.setIdprotese(IdProtese);
        System.out.println("IdProtese= true"+IdProtese );
        ficha.setIdtipopreco(IdTipodePreco);
        ficha.setIdpreco(IdPreco);
        ficha.setIdformadepagamento(IdFormadePagamento);
        ficha.setObservacao(jTextAreaObs);
        ficha.setProva     (prova);
        Date chegada;
        try {
            chegada = (jfdchegada);
            ficha.setChegada(chegada);
        } catch (Exception ex) {
             Logger.getLogger(jIFOs.class.getName()).log(Level.SEVERE, null, ex);
        }
        Date vencendo;
        try {
            vencendo = (jFdPrevisaoEntrega);
            ficha.setVencendo(vencendo);        
        } catch (Exception ex) {
            Logger.getLogger(jIFOs.class.getName()).log(Level.SEVERE, null, ex);
        }
        try{
//            spreco = (Preco);
//        spreco = spreco.replace("R$", "");
            spreco = Preco.replace(",", ".");
            valor = new Double(spreco);
            ficha.setPreco(valor);
        }catch (Exception e){
                        JOptionPane.showMessageDialog(null, "Erro! Lista de Feriados VaziPreço não alterado!!!");
        }
        try{
            ficha.setQuantidade(Qtdeprot);
        }catch (Exception e){
                        JOptionPane.showMessageDialog(null, "Erro! Quantidade não alterada!!!");
        }
        try{
               ficha.setDias(diasUteis);
        }catch (Exception e){
              JOptionPane.showMessageDialog(null, "ERRO: Não entrou no try setDiasUteis(MyTread)!");
        }
        
    }

    private void gravarDiasUteis() {
// Aqui está me parece que está meu problema em relação a esse processo. È que na hora de fazer a atualização dos dados ele dá essa mensagem de erro no catch(exception).      
        try {
            daoFicha = new FichasDao();
            // chamar edita fichas
               editaCamposOsFichas(); // chama a edição de campos para alteração de fichas.
               ficha.setIdos(IdOs);
               ficha.setId  (IdFicha);
               daoFicha.update(ficha);
               System.out.println("diasUteis alterado=" +diasUteis + " Idos="+IdOs+" ficha Id=" + IdFicha);
              JOptionPane.showMessageDialog(null, "Ficha de ordem de serviço (MyTread) ALTERADA com sucesso!");
//        }catch (Exception e){
//              JOptionPane.showMessageDialog(null, "ERRO: Não entrou no try da Alteração da ficha de ordem de serviço(MyTread)!");
//        }
        } catch (SQLException ex) {
            Logger.getLogger(jFOs.class.getName()).log(Level.SEVERE, null, ex);
              JOptionPane.showMessageDialog(null, "ERRO: Não entrou no 1o. Try. (Alteração da ficha de ordem de serviço(MyTread)!)");
        }
        try {
            daoFicha.closeConnection();
        } catch (SQLException ex) {
            Logger.getLogger(jFOs.class.getName()).log(Level.SEVERE, null, ex);
              JOptionPane.showMessageDialog(null, " ERRO: Fechamento da ficha de ordem de serviço!(MyTread)!)");
        }
        
    }
      
       
    
}
// aqui é o meu Dao de alteração das fichas - a minha duvida é que somente preciso alterar o campo em destaque - quantidade de dias. Será que preciso editar todos esses campos para se fazer uma alteração de um só campo no banco?
    @Override
    public void update(Fichas obj) throws SQLException {
        PreparedStatement stmt = getConnection().prepareStatement(
                "UPDATE Fichas "
                + "SET"
                + " idprotese = ?,"
                + "idfabricante = ?, "
                + "idcor = ?, "
                + "idtipopreco = ?, "
                + "idpreco = ?, "
                + "idformadepagamento = ?, "
                + "quantidade = ?, "
                + "preco = ?, "
                + "vencendo = ?, "
                + "conclusao = ?, "
                + "dias = ?, "
                + "selecao = ?, "
                + "prova = ?, "
                + "situacao = ?, "
                + "observacao = ?, "
                + " ultfase = ?, "
                + " dias = ? "
                + "WHERE"
                + " (fichas.idos = ? ) and (fichas.id = ? );" );   


        stmt.setInt( 1, obj.getIdprotese());
        stmt.setInt( 2, obj.getIdfabricante() );
        stmt.setInt( 3, obj.getIdcor() );
        stmt.setInt( 4, obj.getIdtipopreco() );
        stmt.setInt( 5, obj.getIdpreco() );
        stmt.setInt( 6, obj.getIdformadepagamento() );
        stmt.setDouble( 7, obj.getQuantidade() );
        stmt.setDouble( 8, obj.getPreco() );
        stmt.setDate( 9, new java.sql.Date(obj.getVencendo().getTime())); 
        stmt.setDate( 10, new java.sql.Date(obj.getConclusao().getTime())); 
        stmt.setInt( 11, obj.getDias() );
        stmt.setBoolean(12, obj.isSelecao());  
        stmt.setString(13, obj.getProva() );
        stmt.setString( 14, obj.getSituacao() );
        stmt.setString( 15, obj.getObservacao() );
        stmt.setInt( 16, obj.getUltfase() );
 [b]       stmt.setInt( 17, obj.getDias() );[/b]
        stmt.setInt( 18, obj.getIdos() );
        stmt.setInt( 19, obj.getId() );
        stmt.executeUpdate();
        stmt.close();
        
    }
N

Olá wellington.nogueira obrigado por vc ter entrado sempre em contato.

A minha duvida era sobre os dois mas, parece que a Thread já esta executando e o metodo atualizarFaseExecucaoRecepcao() tambem, vou fazer alguns testes para validar se está mesmo fazendo a contagem dos dias uteis como quero. Pra isso, preciso cadastrar muitos dados nas bases para validar. Esse é o primeiro metodo extenso em java com alguns loops e essa era a minha duvida se iria funcionar, mas, parece que já foi resolvida. Obrigado.
Agora quanto a Thread como poderia fazer para que a contagem do clock aparecesse na barra de menu da tela principal do sistema ou então escondê-la do sistema(ficar em background).

Grato pelas respostas.

WellingtonRamos

Dê uma olhada no Quartz para agendamento de execuções.

Dentro da thread, sempre que alguma rotina for atualizar a interface, utilize o SwingUtilities.invokeLater()

public void someMethod(Object... someParams) { //do Something SwingUtilities.invokeLater(new Runnable() { @Override public void run() { // Atualize informações da UI e apenas isso. } }); //do otherthing }

Resp:
1- Quanto a executar desde antes do login, é realmente necessário iniciar ainda na tela de login? Ou podem esperar a tela ser aberta para iniciar a execução?
2- Não tem como prever o comportamento, especialmente com as informações que postou (há muito pouca informação aqui)
3- Não entendi… Essas tabelas são da base de dados ou da UI? creio que seja da base de dados. O que você quis dizer com “Não sei se é a melhor maneira é com arraylist, iterator ou while?”? De qualquer forma, acho que este tópico pode te ajudar: http://www.guj.com.br/java/212207-monitorar-o-banco-de-dados-e-da-um-refresh-na-tabela-apos-nova-insercao
4- O que você já fez? Coloque aqui para analisarmos.

WellingtonRamos

Só pra saber,

Sua dúvida está em:

Thread clockThread = new Thread(new ClockRunnable(), "Clock thread"); clockThread.setDaemon(true); clockThread.start(); ou na implementação do método atualizarFaseExecucaoRecepcao(); ?

Eu acredito que seja na segunda parte. Mas aí, toda aexecução está, ao que me parece, ocorrendo dentro da Thread AWTEvent. (Não testei o código)

WellingtonRamos

Sua aplicação não trava durante a execução do método atualizarFaseExecucaoRecepcao?

WellingtonRamos

Certamente elas estão executando, uma está na thread que você criou e outra, na thread onde o Swing executa.

Acho que no método atualizarFaseExecucaoRecepcao poderia fazer da mesma forma que fez no clockThread. Adicionar o conteúdo em outra thread e os momentos em que necessita atualizar a UI (incluindo as chamadas para o JOptionPane), usar o SwingUtilities.

Criado 25 de fevereiro de 2013
Ultima resposta 26 de fev. de 2013
Respostas 6
Participantes 2