[RESOLVIDO] Importar dados para um banco usando Thread | Java

Olá! Estou desenvolvendo um programa que importa dados para um banco e coleta dados de lá. Tudo funciona normalmente, mas é muito demorado então resolvi usar uma Thread, porém parece que a importação não é feita quando uso ela, apenas a coleta de dados funciona… Poderiam ajudar?

[code]
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.LinkedList;

import javax.swing.JOptionPane;

import model.Colaborador;
import model.Maquina;

public class ImportarBanco implements Runnable {

private Conexao conexao;
private LinkedList<Colaborador> colaboradores;
private HashMap<String, Maquina> maquinas;

public ImportarBanco(Conexao c, LinkedList<Colaborador> colaboradores,
		HashMap<String, Maquina> maquinas) {
	this.setConexao(c);
	this.setColaboradores(colaboradores);
	this.setMaquinas(maquinas);
	Thread thread = new Thread(this);
	thread.start();
}

@Override
public void run() {
	this.importar();
}

private void importar() {
	importarColaboradores();
	importarMaquinas();
}

// Importa os colaboradores para dentro do Banco de Dados
private void importarColaboradores() {
	try {
		this.delete("colaboradores");

		String sql = "INSERT INTO colaboradores (nome, cc, crc, empresa, gestor) VALUES (?,?,?,?,?)";
		this.getConexao().conectar();
		PreparedStatement pstmt = null;
		for (Colaborador c : this.getColaboradores()) {

			// Parâmetros
			pstmt = this.getConexao().criarPreparedStatement(sql);
			pstmt.setString(1, c.getNome());
			pstmt.setString(2, c.getCc());
			pstmt.setString(3, c.getCrc());
			pstmt.setString(4, c.getEmpresa());
			pstmt.setString(5, c.getGestor());

			// Executar
			pstmt.execute();
		}
	} catch (SQLException erro) {
		System.out.println("Mensagem: " + erro.getMessage());
		System.out.println("Causa: " + erro.getCause());
		erro.printStackTrace();
		JOptionPane.showMessageDialog(null,
				"Falha ao importar os colaboradores | Código: 16 \n(" + erro.getMessage() + ")", "Sistema",
				JOptionPane.ERROR_MESSAGE);
	} finally {
		this.getConexao().desconectar();
	}
}

// Importa as máquinas para dentro do Banco de Dados
private void importarMaquinas() {
	this.delete("maquinas");
	try {

		String sql = "INSERT INTO maquinas (patrimonio, proprietario, crc, equipamento, descricao, dataRecebimento, historico) VALUES (?,?,?,?,?,?,?)";
		this.getConexao().conectar();
		PreparedStatement pstmt = this.getConexao().criarPreparedStatement(sql);
		for (Maquina m : this.getMaquinas().values()) {

			// Parâmetros
			pstmt.setString(1, m.getPatrimonio());
			pstmt.setString(2, m.getProprietario().getNome());
			pstmt.setString(3, m.getCrc());
			pstmt.setString(4, m.getEquipamento());
			pstmt.setString(5, m.getDescricao());
			pstmt.setString(6, String.valueOf(m.getDataRecebimento()));
			pstmt.setString(7, m.getHistoricoString());

			// Executar
			pstmt.execute();
		}
	} catch (SQLException erro) {
		System.out.println("Mensagem: " + erro.getMessage());
		System.out.println("Causa: " + erro.getCause());
		erro.printStackTrace();
		JOptionPane.showMessageDialog(null,
				"Falha ao importar as máquinas | Código: 17 \n(" + erro.getMessage() + ")", "Sistema",
				JOptionPane.ERROR_MESSAGE);
	} finally {
		this.getConexao().desconectar();
	}
}

}

[code]

A classe mostrada acima é chamada ao fechar o JFrame da aplicação:

[code]

	addWindowListener(new WindowAdapter() {
		@SuppressWarnings("unused")
		@Override
		public void windowClosing(WindowEvent arg0) {
			try {
				Conexao conexao = new Conexao();
				ImportarBanco bd = new ImportarBanco(conexao, getColaboradores(), getMaquinas());

			} catch (Exception e) {
				System.out.println(e.getMessage());
			}
		}
	});

[code]

Ao realizar o debug, vi que os métodos não são executados se estiver com a Thread implementada. Caso ela não esteja, a importação ocorre normalmente.

Obrigado!

Olhando rapidamente, o que parece estar acontecendo é que não está dando tempo da thread realizar a tarefa dela, pois a thread principal, em que o programa está em execução, está finalizando antes.

Em relação à demora para processar os dados vai continuar acontecendo, não é pq vc colocou essa tarefa em uma thread que o processo se tornará mais rápido…

Enfim, acredito que isso resolva seu problema, apesar de eu não gostar sua solução:

addWindowListener(new WindowAdapter() {
    @SuppressWarnings("unused")
    @Override
    public void windowClosing(WindowEvent arg0) {
        try {
            Conexao conexao = new Conexao();
            ImportarBanco bd = new ImportarBanco(conexao, getColaboradores(), getMaquinas());
            Thread.join(); // faz a thread atual aguardar a que está em
                           // execução finalizar para continar a executar
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
});

Por acaso no seu JFrame você setou o setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)?

Sim! Mas eu marquei para Dispose e deixei que a importação fosse feita por outro JFrame.

Obrigado! Me baseei na sua resposta pra montar uma solução: deixei o JFrame como DISPOSE_ON_CLOSE e criei um JFrame com uma barra de carregamento que realiza a importação. Muito obrigado novamente!

pois é, isso significa que, independente de ter listeners no seu JFrame, ele vai fazer um System.exit(0) ao ser fechado.

Eu deixaria o JFrame com DO_NOTHING_ON_CLOSE e mudaria meu WindowListener dessa forma:

public void windowClosing(WindowEvent arg0) {
    try {
        Conexao conexao = new Conexao();
        ImportarBanco bd = new ImportarBanco(conexao, getColaboradores(), getMaquinas());
        bd.aguardar(); // cria esse método na classe ImportatBanco para fazer um `join` na `Thread`
        System.exit(0); // se chegou até aqui, deu tudo certo, posso encerrar
    } catch (Exception e) {
        System.out.println(e.getMessage());
    }
}

Essa forma que apresentou também resolve meu problema. Muito obrigado!