我正在开发一个javafx应用程序。由于我需要显示数据库中的一些数据,我开始了解在Javafx中使用Task
。在看到SO上的解决方案后,我尝试实现它。为了检查它是否有效,我只是在HashTable中打印了一个从数据库中获得的团队列表。
当我第一次启动应用程序时,数据被成功提取并显示在我的控制台上,但当我切换场景并尝试切换回主页(提取数据的地方(时,UI完全冻结,甚至不显示场景。
主页.java
public class Home implements Initializable {
private Executor executor;
private TeamsDAO teamsDAO;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
try{
teamsDAO = new TeamsDAO();
}catch (SQLException e){
e.printStackTrace();}
executor = Executors.newCachedThreadPool(runnable -> {
Thread th = new Thread(runnable);
th.setDaemon(true);
return th;
});
printTeams();
}
public void printTeams() {
Task<Hashtable<Integer, String>> displayTask = new Task<Hashtable<Integer, String>>() {
@Override
protected Hashtable<Integer, String> call() throws Exception {
return teamsDAO.getTeams();
}
};
displayTask.setOnFailed(e -> {
displayTask.getException().printStackTrace();
});
displayTask.setOnSucceeded(e -> {
cricProTitle.setText(displayTask.getValue().get(2));
});
executor.execute(displayTask);
}
}
我使用HikariCP作为postgresql的数据库连接池。
TeamsDAO.java
public class TeamsDAO {
private Connection conn;
public TeamsDAO() throws SQLException {
this.conn = DataSource.getConnection();
}
public Hashtable<Integer, String> getTeams() throws SQLException {
try (PreparedStatement pst = conn.prepareStatement("SELECT * FROM TEAMS")) {
ResultSet rs = pst.executeQuery();
Hashtable<Integer, String> teams = new Hashtable<>();
while (rs.next()) {
teams.put(rs.getInt("team_id"), rs.getString("name"));
}
return teams;
}
}
}
UI冻结时不会显示错误堆栈跟踪。我希望这些团队能显示在主页上(在线程成功工作后(。请告诉我哪里出了问题?
当我在initialize
方法中启动TeamsDAO
对象时,每次我切换回主控制器时,它都会创建一个新的数据库连接,从而填充连接池。为了解决这个问题,我在Home.java中创建了一个静态块,只提取了一次所需的数据。
更新的Home.java:
public class Home implements Initializable {
private static TeamsDAO teamsDAO;
@FXML
private BorderPane borderPane;
@FXML
private Label cricProTitle;
@FXML
private Label homepageLabel;
@FXML
private Label banner;
@FXML
private GridPane buttonContainer;
static {
try {
teamsDAO = new TeamsDAO();
} catch (SQLException e) {
e.printStackTrace();
}
Task<Hashtable<Integer, String>> task = new Task<>() {
@Override
protected Hashtable<Integer, String> call() throws Exception {
return teamsDAO.getTeams();
}
};
task.setOnSucceeded(e -> {
System.out.println(task.getValue());
});
Thread x = new Thread(task);
x.setDaemon(true);
x.start();
System.out.println(x.getState());
}
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
//setting UI properties here..
}
}