我的GUI包含JTable
和几个可能触发INSERT
,UPDATE
或DELETE
SQL查询的表单。无论何时发生,我都希望我的表格相应更新。由于必须更新TableModel
和远程SQL表,因此有几种方法可以继续。
首先更新SQL表,然后SELECT
更改已修改的数据,然后调用fireTableDataChanged()
。这就是我目前正在做的事情。它保证表和数据库完美同步。但是,TableModel
在从ResultSet
中提取数据之前不会更新,在我的情况下,整个事情平均需要0.5到1秒。这不是太糟糕,但也不是太好。
同时更新这两个版本,修改TableModel
以匹配我对以前的方法的预期。这可以提高客户端的性能,因为更改几乎是即时的,并且SQL内容将“在后台”运行。但是我不确定在表和数据库之间失去同步,这看起来像是肮脏的方式。
混合使用这两种方法。也许快速,单细胞更新应使用第二种方法,而INSERT
和DELETE
s则需要第一种方法?虽然效率更高,但感觉不一致。
还有其他办法吗?
我该怎么办?请分享您对此事的经验。
答案 0 :(得分:1)
我喜欢您使用JTable
从SQL表中更新SELECT
的首选。
如果您担心0.5-1秒暂停 - 您可以按以下方式混合第一个和第二个变体:立即用“预期”结果更新表,执行SQL,然后SELECT
修改数据并检查它是否是与当前相同。我认为在大多数情况下它们将是相同的,因此不需要更新JTable
,而且还可以获得同步模型。
答案 1 :(得分:1)
我想到的第一种方法是创建AbstractTableModel
的子类,并将数据存储在其私有ArrayList<?>
字段中。在其构造函数中,使用要在表中显示的数据查询数据库。
如果在表中添加了一行,则会向数据库触发带有插入数据的INSERT
语句。
如果对表中的单元格进行了更新,请验证是否可以进行更新。如果可能,将向DB
触发UPDATE
如果删除了一行,则会向DB发出DELETE FROM
语句。
public class MyTableModel extends AbstractTableModel{
private List<Person> dataSource;
public MyTableModel(){
dataSource = new ArrayList<Person>();
//query the database then add the queried data to the dataSource,
//you should do it in the background, using SwingWorker
//call fireTableRowsInserted with proper arguments
}
@Override
public int getColumnCount() {
return 3;
}
@Override
public int getRowCount() {
return dataSource.size();
}
@Override
public Object getValueAt(int row, int col) {
Object retVal = null;
if(col == 0)dataSource.get(row).getFirstName();
else if(col == 1)dataSource.get(row).getLastName();
else if(col == 2)dataSource.get(row).getOccupation();
return retVal;
}
@Override
public void setValueAt(Object value, int row, int col){
//validate if the update is possible, if yes proceed
//update the value in the DB
//update the value in the arraylist
//call super.setValueAt(value, row, col);
}
public void addRow(Person p){
//validate if the person is insertable, if yes proceed
//INSERT the person to the DB
//add the person to the arraylist
//call fireTableRowsInserted
}
public void deleteRow(int row){
//call fireTableRowsDeleted
}
}
答案 2 :(得分:1)
首先更新SQL表,然后SELECT
更改已修改的数据,并使用返回的TableModel
创建新的ResultSet
。这就是我现在正在做。它保证表和数据库完美同步。但是,TableModel
在从ResultSet
中提取数据之前不会更新,在我的情况下,整个事情平均需要0.5到1秒。这不是太糟糕,但也不是太好。
错误的想法创建一个新的XxxTableModel不仅仅是反作用,一个XxxTableModel可以用于所有视图,对于一些JTables / JLists只有在没有使用RowSorter或RowFilter的情况下通知,那么代码中的逻辑必须包含基于一个XxxTableModel的所有JTable的过滤排序
用于创建单独的XxxTableModels的静态数据(StandingData)
同时更新这两个版本,修改TableModel
以匹配我对以前的方法的预期。这可以提高客户端的性能,因为更改几乎是即时的,并且SQL内容将“在后台”运行。但我不确定在表和数据库之间失去同步,这看起来像是肮脏的方式。
不知道,基本上如果输入掩码(表格)中的值存储在数据库中,则应刷新JTable并以默认值结束输入表单
可能是方式,但需要同步数据库,它在JTable和输入掩码中的镜像
混合使用这两种方法。也许快速,单细胞更新应使用第二种方法,而INSERT
和DELETE
s则需要第一种方法?虽然效率更高,但感觉不一致。
还有其他办法吗?
是的,有几种方法,但My GUI includes a JTable and several forms that may ...
可以使简单的事情复杂化
使用
创建一个JFrameJSplitPane可能有一个区域用于CardLayout铺设的所有输入掩码,第二个用于JTable,只有一个JTable,有一个XxxTableModel(您可以在JList中添加StandindData或在南部或西部/东部地区添加另一个JTable)意图填补容器中的可用空间)
使用BorderLayout,中间是CardLayout铺设的输入掩码,请参阅上述第1点的其余部分。
将一些JTables / Lists(例如参见Bloomberg或Reuters Xtra3000的屏幕)添加到一个JFrame中,使用JMenuItems为这些对象添加JPopupMenu添加,修改,删除,修改...... JTables中的项目/列表,然后只创建一个由CardLayout布局的JDialog,并在应用程序启动时包含所有输入掩码,然后从JPopupMenu输出将包含三个代码行切换到基于源的卡,JDialog的调用包,调用JDialog的setVisible(true) ,但必须包装到invokeLater,
在调用setVisible(false)之前将数据保存在数据库中后重置输入掩码中的所有JComponents,否则下一个可见性可以使用JComponent中的值闪烁/刷新
没人保证来自输入掩码的数据保存在数据库中并且正确,
e.g。可以有定义的触发器,填充其余列的值,然后所有数据流可以是异步的,由内部数据库规则延迟
数据流必须是将数据保存到数据库,如果PreparedStatement执行无异常,那么你可以刷新输入掩码为默认值,下一步可能是将数据加载到XxxMableModel,如果有弹出JDialog ,现在是隐藏JDialog的时刻
如果有异常,则输入掩码及其值不会发生任何事情,对用户来说更好,更安全,可以基于模拟,可以创建截图然后报告它。 ..