所以,我在javaFX中创建一个应用程序(仅用于学习目的),它主要由每个选项卡的子fxmls的tabpane组成。每个选项卡都包含一个tableview,其中包含从数据库收集的数据。为了连接到数据库,我有一个单独的连接类,它使用c3p0创建一个新的连接池。
我的第一个问题是:我是否应该为每次对数据库进行的查询创建(并关闭)新连接?
示例:输入新选项卡后,我创建一个新连接,收集数据,然后关闭连接(使用语句和结果集)。
如果没有,我将如何以适当和有效的方式做到这一点?
我的第二个问题:目前我的应用程序正在执行上述操作,但我注意到如果我将应用程序打开一段时间而不与之交互,每当我再次开始与它进行交互时,它就会冻结在它继续之前。当时查看的当前表格显示"表格中没有数据",直到我切换到另一个选项卡,然后数据再次正确显示。为什么会这样?
我对Java一般都很陌生,而且通过搜索类似于我的问题我找不到任何东西。我的数据库是postgres db。
编辑1: 关于问题2: 我已经遵循了mvc-pattern,不确定这是不是一个好主意,但这是另一个问题。
有四个类在表的创建中起作用,它们是:
控制器类:
public class StockController {
//tableview from fxml-file
@FXML
private TableView<List<Object>> stockTable;
//
private BuildDataModel stockData = new BuildDataModel();
//Called from main whenever currently active tab changes to this tab.
public void CreateView(){
String query = "SELECT component.name, stock.* FROM component NATURAL JOIN stock";
stockData.BuildData(stockTable, query);
}
//Called from main whenever currently active tab changes to another tab.
public void DestroyView(){
if(!stockTable.getColumns().isEmpty()) {
stockData.DeleteData();
}
}
}
模特课:
public class BuildDataModel {
private Connection conn;
@FXML
private TableView<List<Object>> tableview;
public TableData data;
private TableData getAllData(String query){
List<List<Object>> data = new ArrayList<>();
List<String> columnNames = new ArrayList<>();
PreparedStatement st = null;
ResultSet rs = null;
try {
conn = PostgresConnection.CreateConnection();
st = conn.prepareStatement(query);
rs = st.executeQuery();
//We create columns
int columnCount = rs.getMetaData().getColumnCount();
for(int i = 1; i <= columnCount; i++) {
String columnName = rs.getMetaData().getColumnName(i);
columnNames.add(columnName);
}
//We populate our tabledata object with the data
while(rs.next()){
List<Object> row = new ArrayList<>();
for(int i = 1; i <= columnCount; i++){
row.add(rs.getObject(i));
}
data.add(row);
}
}
catch (Exception e){
e.printStackTrace();
}
finally {
DbUtils.closeQuietly(conn, st, rs);
}
return new TableData(columnNames, data);
}
//Called from controller class, calls getAllData with the specified query
//and populates tableview based on this.
public void BuildData(TableView<List<Object>> tableview, String query) {
this.tableview = tableview;
try {
data = getAllData(query);
for (int i = 0 ; i < data.getNumColumns(); i++) {
TableColumn<List<Object>, Object> column = new TableColumn<>(data.getColumnName(i));
int columnIndex = i;
column.setCellValueFactory(cellData ->
new SimpleObjectProperty<>(cellData.getValue().get(columnIndex)));
tableview.getColumns().add(column);
}
tableview.getItems().setAll(data.getData());
}
catch (Exception e) {
}
}
public void DeleteData(){
tableview.getColumns().clear();
}}
连接类:
public class PostgresConnection {
//DB credentials, modify as needed
private static final String HOST = "localhost";
private static final String DATABASE = "<INSERT DATABASE HERE>";
private static final String USERNAME = "<INSERT USERNAME HERE>";
private static final String PASSWORD = "<INSERT PASSWORD HERE>";
//Default postgresql port, don't change unless you know what you're doing.
private static final String PORT = "5432";
private static final String URL = "jdbc:postgresql://" + HOST + ":" + PORT + "/" + DATABASE;
private static final String DRIVER_NAME = "org.postgresql.Driver";
private static Connection conn;
//Disables C3P0-pool logging
static {
Properties p = new Properties(System.getProperties());
p.put("com.mchange.v2.log.MLog", "com.mchange.v2.log.FallbackMLog");
p.put("com.mchange.v2.log.FallbackMLog.DEFAULT_CUTOFF_LEVEL", "OFF");
System.setProperties(p);
}
private static ComboPooledDataSource cpds = new ComboPooledDataSource();
public static Connection CreateConnection() throws SQLException {
try {
cpds.setDriverClass(DRIVER_NAME);
} catch (PropertyVetoException e) {
e.printStackTrace();
}
cpds.setJdbcUrl(URL);
cpds.setUser(USERNAME);
cpds.setPassword(PASSWORD);
cpds.setMinPoolSize(3);
cpds.setAcquireIncrement(5);
cpds.setMaxPoolSize(100);
cpds.setMaxStatements(180);
return cpds.getConnection();
}}
和DAO:
public class TableData {
private final List<String> columnNames;
private final List<List<Object>> data;
public TableData(List<String> columnNames, List<List<Object>> data) {
this.columnNames = columnNames;
this.data = data;
}
public int getNumColumns() {
return columnNames.size();
}
public String getColumnName(int index) {
return columnNames.get(index);
}
public int getNumRows() {
return data.size();
}
public Object getData(int column, int row) {
return data.get(row).get(column);
}
public List<List<Object>> getData() {
return data;
}
public void removeData(){
data.clear();
columnNames.clear();
}}