java - 在包含数据库数据的列表中使用线程
问题描述
我试图在我在数据库中进行的查询中使用一个线程,该线程可以生成许多我不知道是否有必要的记录但是当我尝试实现线程时它没有返回该列表中的值(没有线程它通常返回值)
我的控制器:在这里我调用我的方法,该方法将包含我的 DAO 类数据库列表:
public ObservableList<Requisicao> atualizarTabela() {
RequisicaoDAO dao = new RequisicaoDAO();
requisicoes = FXCollections.observableArrayList(dao.getList());
return requisicoes;
}
我的方法 DAO:
public class RequisicaoDAO {
private Connection con;
Alerts alerts = new Alerts();
public RequisicaoDAO() {
this.con = new ConnectionFactory().getConnection();
}
private static RequisicaoDAO aRequisicaoDAO;
public static RequisicaoDAO getInstancia() {
if (aRequisicaoDAO == null) {
aRequisicaoDAO = new RequisicaoDAO();
}
return aRequisicaoDAO;
}
public List<Requisicao> getList() {
List<Requisicao> requisicoes = new ArrayList<>();
new Thread() {
@Override
public void run() {
String sql = "SELECT * FROM equipamento_requisicao equipreq INNER JOIN equipamento_user equipuser ON (equipreq.idequipamento_user = equipuser.id_equipamento_do_usuario) INNER JOIN usuario user ON (user.id_usuario=equipuser.idusuario) INNER JOIN equipamentos equip ON (equip.id_equipamentos = equipuser.idequipamentos) INNER JOIN detalhe_status dStatus ON (dStatus.idequipamento_requisicao= equipreq.id_equipamento_requisicao) INNER JOIN status_requisicao statusreq on (statusreq.id_status= dStatus.idstatus) INNER JOIN permissao p ON(user.idpermissao= p.id_permissao) INNER JOIN departamentos dp ON(user.iddepartamento = dp.id_departamentos) INNER JOIN chefe_departamento cp ON(dp.id_chefe = cp.id_chefe) where statusreq.categoria='Ativa' ";
try {
PreparedStatement stmt = con.prepareStatement(sql);
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
Usuario usuario = new Usuario();
usuario.setNome(rs.getString("user.nome"));
usuario.setId(rs.getLong("user.id_usuario"));
usuario.setMatricula(rs.getString("user.matricula"));
// FIM TABELA USUARIO
//equipamento // equipamento user tabelas
Equipamentos equipamento = new Equipamentos();
equipamento.setEquipamento_nome(rs.getString("equip.equipamento_nome"));
equipamento.setSerial_equipamento(rs.getString("equipuser.serial_equipamento"));
equipamento.setId_equipamento_do_Usuario(rs.getLong("equipreq.idequipamento_user"));
//status tabela
Status status = new Status();
status.setCategoria(rs.getString("statusreq.categoria"));
status.setIdstatus(rs.getInt("statusreq.id_status"));
//status detalhes tabela
Usuario usuarioStatus = new Usuario();//id do usuaro na tabela detalhes status
usuarioStatus.setId(rs.getLong("dStatus.idusuario"));
StatusDetalhes statusDetalhes = new StatusDetalhes();
statusDetalhes.setId_statusdetalhes(rs.getLong("dStatus.id_statusdetalhes"));
statusDetalhes.setData_status(rs.getTimestamp("dStatus.data"));
statusDetalhes.setObservacao_status(rs.getString("dStatus.observacao"));
statusDetalhes.setIdUsuario(usuarioStatus);
statusDetalhes.setIdStatus(status);
// Id da requisicao na tabela detalhes status
Requisicao requisicaoStatus = new Requisicao();
requisicaoStatus.setId(rs.getLong("dStatus.idequipamento_requisicao"));
//requisicao tabela
Requisicao req = new Requisicao();
req.setId(rs.getLong("equipreq.id_equipamento_requisicao"));
req.setNome(rs.getString("equipreq.nome"));
req.setData_criada(rs.getTimestamp("equipreq.data_requisicao"));
req.setMotivo(rs.getString("equipreq.observacao"));
req.setReqEquipamento(equipamento);
req.setReqStatus(status);
req.setReqUsuario(usuario);
req.setReqStatus_Detalhes(statusDetalhes);
requisicoes.add(req);
}
stmt.close();
rs.close();
} catch (SQLException ex) {
Logger.getLogger(RequisicaoDAO.class.getName()).log(Level.SEVERE, null, ex);
}
}
}.start();
return requisicoes;
}
}
不会产生任何错误,但我没有在我的表格视图中得到这个列表我认为问题出在返回 requisicoes 中;但我无法解决。
解决方案
问题是,您requisicoes
在线程向其添加任何内容之前返回值。
因为 Thread 是异步执行的,所以执行看起来像这样:
所以查询工作正常(不使用线程时你会看到正确的结果),但是它们被添加到列表中很晚,因为(空)列表已经复制到新的可观察列表中,因此添加了结果不再影响控制器中的可观察列表。
一个解决方案可能是在返回列表之前等待线程的执行requisicoes
(通过调用线程的join 方法。但这会导致该方法getList()
花费很多时间(因为它正在等待线程),这可能是你想要的通过使用线程来避免。
另一个(可能更好)的解决方案是从方法中删除多线程,getList()
并使用任务将多线程添加到控制器中。
解决方案可能如下所示:
public ObservableList<Requisicao> atualizarTabela() {
RequisicaoDAO dao = new RequisicaoDAO();
//create an empty list first
requisicoes = FXCollections.observableArrayList();
//execute the query in the task
Task<List<Requisicao>> task = new Task<List<Requisicao>>() {
@Override
protected List<Requisicao> call() throws Exception {
//getList has no thread anymore
return dao.getList();
}
};
//add the list values to the observable list, when the task succeeds
task.setOnSucceeded(e -> requisicoes.addAll(task.getValue()));
task.setOnFailed(e -> System.out.println("Task failed"));//better do some execption handling here...
//start the task in a new thread
Thread executor = new Thread(task, "get_list_task_thread");
executor.start();
//return the (empty) list, which will be filled when the task (that includes the query) has finished
return requisicoes;
}
如果您像这样更改代码(并从方法中删除线程,getList()
它应该首先返回一个空的ObservableList
,在任务(包括查询)完成后显示和填充。这个解决方案的优点是,它没有t 在执行查询时停止执行 FX-Thread,因此 UI 不会停止。
推荐阅读
- ios - 向其子视图(即 UILabel)添加约束时,无法保持集合视图单元格的固定大小
- c++ - 使用 std::map 计算 input.txt 中的单词。需要使其不区分大小写
- python - 如何在单击 Python Dash 的按钮上添加单独的 Html 元素
- django - Django Cache - 模型更改时更新
- laravel - 为什么在我完成输入之前 Visual Studio 会中断到下一行
- json - protobuf 如何帮助或简化消息流的模式验证?
- android - 如何使 TableLayout 在 ConstraintLayout 中垂直居中,并在其下方放置一些东西?
- r - 如何删除 y.axis 面板边框?
- c# - Linq2Couchbase 加入 List<> 到 id
- azure - 如何在 Azure Logic App 中将电子邮件作为附件阅读