How do I query in a database from a thread? [closed]

-3

A teacher asked to develop a project (a CRUD of cars). I've done the insert, remove, list, and change part.

But the list part must be done by a thread (teacher's requirement), where it must list a car every 20 seconds and show in JTextArea . My question is how to make the thread do this.

Follow the code:

% class of% to list. Note: I have not done anything in this class yet:

public class ThreadListar implements Runnable{


    private int tempo;


    public ThreadListar(int tempo) {
        this.tempo=tempo;

        Thread t1=new Thread(this);
        t1.start();

    }



    @Override
    public void run() {

        try {
            Thread.sleep(tempo);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}

Class Thread with list method:

@Override
public ArrayList<Carro> listar() {

    ArrayList<Carro> carros= new ArrayList<Carro>();
    String sql="select * from carro";

try(Connection con= new ConnectionFactory().getConnection()){

    PreparedStatement ps= con.prepareStatement(sql);

    ResultSet rs= null;

    rs=ps.executeQuery();

    while(rs.next()) {

        Carro c= new Carro();

        c.setId(rs.getInt("id"));
        c.setMarca(rs.getString("marca"));
        c.setModelo(rs.getString("modelo"));
        c.setCor(rs.getString("cor"));
        c.setPlaca(rs.getString("placa"));

        carros.add(c);
    }   

    ps.close();
    rs.close();

}catch(SQLException e){

    JOptionPane.showMessageDialog(null, "Erro ao realziar consulta:"+e, "ERROR", JOptionPane.ERROR_MESSAGE);
    throw new RuntimeException(e);

}
    return carros;
}

Class CarroDAO (swing) with the button and the action of listing and setting the data within Tela :

public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                Tela frame = new Tela();
                frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });

}

public Tela() {


JButton btnListar = new JButton("Listar");
    btnListar.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {



            CarroDAO dao1 = new CarroDAO();

            ArrayList carros= dao1.listar();

            for(Object o: carros) {

                Carro c= (Carro) o;


                textArea.append(String.valueOf("ID: "+c.getId()+"\n"));
                textArea.append("Marca: "+c.getMarca()+"\n");
                textArea.append("Modelo: "+c.getModelo()+"\n");
                textArea.append("Cor: "+c.getCor()+"\n");
                textArea.append("Placa: "+c.getPlaca()+"\n"+"\n");
                textArea.append("=================");
            }

        }
    });


    btnListar.setBounds(234, 233, 89, 23);
    contentPane.add(btnListar);
    }
}
}
    
asked by anonymous 02.11.2017 / 22:16

2 answers

1

The Articuno answer is on the right track. However, separating what goes into the EDT from what goes in the thread is easier using SwingWorker , even taking care to query the DAO outside the EDT on an auxiliary thread:

public class Tela extends JFrame {

    private final JButton btnListar;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Tela().setVisible(true));
    }

    public Tela() {
        this.btnListar = new JButton("Listar");
        btnListar.addActionListener(e -> realizarListagem());
        btnListar.setBounds(234, 233, 89, 23);
        contentPane.add(btnListar);
    }

    private void realizarListagem() {
        btnListar.setEnabled(false);
        SwingWorker<Void, Carro> worker = new SwingWorker<Void, Carro>() {
            @Override
            protected Void doInBackground() {
                ScheduledExecutorService ses = Executors.newScheduledThreadPool(1);

                // Usamos o Iterator para acessar um carro por vez.
                Iterator<Carro> it = new CarroDAO().listar().iterator();

                Runnable run = () -> {
                    if (isCancelled() || !it.hasNext()) {
                        ses.shutdown();
                    } else {
                        // Pega o próximo carro e publica.
                        publish(it.next());
                    }
                };

                // Executa o Runnable uma vez a cada 20 segundos.
                ses.scheduleAtFixedRate(run, 0, 20, TimeUnit.SECONDS);

                // Espera a lista de carros terminar.
                try {
                    ses.awaitTermination(99999, TimeUnit.DAYS);
                } catch (InterruptedException e) {
                    // Ignora a exceção e deixa o SwingWorker terminar graciosamente.
                }
                return null;
            }

            @Override
            protected void process(List<Carro> carros) {
                // Isto daqui NÃO deve ser uma lista com todos os carros.
                // Na verdade, espera-se que este método seja chamado com
                // um carro por vez.
                for (Carro c : carros) {
                    textArea.append(String.valueOf("ID: " + c.getId() + "\n"));
                    textArea.append("Marca: " + c.getMarca() + "\n");
                    textArea.append("Modelo: " + c.getModelo() + "\n");
                    textArea.append("Cor: " + c.getCor() + "\n");
                    textArea.append("Placa: " + c.getMarca() + "\n\n");
                    textArea.append("=================");
                }
            }

            @Override
            protected void done() {
                btnListar.setEnabled(true);
            }
        };
        worker.execute();
    }
}

Your DAO also has a problem: If you're already using try-with-resources, then there should be no sense to call the close() method explicitly. Here's how your revised code looks:

private static final String INSERT_SQL = "SELECT * FROM Carro";

@Override
public List<Carro> listar() {

    List<Carro> carros = new ArrayList<>();

    try (
        Connection con = new ConnectionFactory().getConnection();
        PreparedStatement ps = con.prepareStatement(SQL);
        ResultSet rs = ps.executeQuery();
    ) {
        while (rs.next()) {
            Carro c = new Carro();
            c.setId(rs.getInt("id"));
            c.setMarca(rs.getString("marca"));
            c.setModelo(rs.getString("modelo"));
            c.setCor(rs.getString("cor"));
            c.setPlaca(rs.getString("placa"));
            carros.add(c);
        }
    } catch (SQLException e) {
        JOptionPane.showMessageDialog(null, "Erro ao realziar consulta: " + e, "ERROR", JOptionPane.ERROR_MESSAGE);
        throw new RuntimeException(e);
    }
    return carros;
}

And notice that I've changed the return from ArrayList<Carro> to List<Carro> . There is a programming principle that says " code to an interface, not an implementation ". Well, List is an interface and ArrayList is an implementation.

    
03.11.2017 / 05:50
1

Due to the need to use a separate thread and timing thread, you can use the ScheduledExecutorService , which is used to schedule tasks in the JVM, and execute them repeatedly (if necessary) in a parallel-to-current thread pool. Bear in mind that swing is not Thread-Safe , so we should stick to change the component in the same thread responsible for the graphical interface, the event-dispatch-thread .

In the example below, I only create a thread using the newScheduledThreadPool() method and set the execution with the scheduleAtFixedRate() method, which receives as parameters the task that will be executed, the initial delay to start it, the time interval between each execution and the unit of time.

Finally, within the task, I used a counter to display the values of the list with each repetition of the task, and also so that it can be finalized when it reaches the end of the list. The variable must be a field of the class, otherwise it will not be possible to modify it.

...

//o contador deverá ser uma variável de classe
private volatile int index = 0;

...

btnListar.addActionListener(e -> {

    CarroDAO dao1 = new CarroDAO();

    List<Carro> carros = dao1.listar();

    ScheduledExecutorService ses = Executors.newScheduledThreadPool(1);

    Runnable run = () -> {

        if (index < carros.size()) {
            SwingUtilities.invokeLater(() -> {
                textArea.append(String.valueOf("ID: " + carros.get(index).getId() + "\n"));
                textArea.append("Marca: " + carros.get(index).getMarca() + "\n");
                textArea.append("Modelo: " + carros.get(index).getModelo() + "\n");
                textArea.append("Cor: " + carros.get(index).getCor() + "\n");
                textArea.append("Placa: " + carros.get(index).getMarca() + "\n" + "\n");
                textArea.append("=================");
                index++;
            });
        } else {
            index = 0;
            ses.shutdown();
        }

    };
    ses.scheduleAtFixedRate(run, 0, 20, TimeUnit.SECONDS);

});
    
03.11.2017 / 00:54