在使用SQL时,我应该如何处理TableModel更新?

时间:2013-06-13 09:22:13

标签: java sql swing jtable

我的GUI包含JTable和几个可能触发INSERTUPDATEDELETE SQL查询的表单。无论何时发生,我都希望我的表格相应更新。由于必须更新TableModel和远程SQL表,因此有几种方法可以继续。

  • 首先更新SQL表,然后SELECT更改已修改的数据,然后调用fireTableDataChanged()这就是我目前正在做的事情。它保证表和数据库完美同步。但是,TableModel在从ResultSet中提取数据之前不会更新,在我的情况下,整个事情平均需要0.5到1秒。这不是太糟糕,但也不是太好。

  • 同时更新这两个版本,修改TableModel以匹配我对以前的方法的预期。这可以提高客户端的性能,因为更改几乎是即时的,并且SQL内容将“在后台”运行。但是我不确定在表和数据库之间失去同步,这看起来像是肮脏的方式。

  • 混合使用这两种方法。也许快速,单细胞更新应使用第二种方法,而INSERTDELETE s则需要第一种方法?虽然效率更高,但感觉不一致。

  • 还有其他办法吗?

我该怎么办?请分享您对此事的经验。

3 个答案:

答案 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)

  1. 首先更新SQL表,然后SELECT更改已修改的数据,并使用返回的TableModel创建新的ResultSet这就是我现在正在做。它保证表和数据库完美同步。但是,TableModel在从ResultSet中提取数据之前不会更新,在我的情况下,整个事情平均需要0.5到1秒。这不是太糟糕,但也不是太好。

    • 错误的想法创建一个新的XxxTableModel不仅仅是反作用,一个XxxTableModel可以用于所有视图,对于一些JTables / JLists只有在没有使用RowSorter或RowFilter的情况下通知,那么代码中的逻辑必须包含基于一个XxxTableModel的所有JTable的过滤排序

    • 用于创建单独的XxxTableModels的静态数据(StandingData)

  2. 同时更新这两个版本,修改TableModel以匹配我对以前的方法的预期。这可以提高客户端的性能,因为更改几乎是即时的,并且SQL内容将“在后台”运行。但我不确定在表和数据库之间失去同步,这看起来像是肮脏的方式。

    • 不知道,基本上如果输入掩码(表格)中的值存储在数据库中,则应刷新JTable并以默认值结束输入表单

    • 可能是方式,但需要同步数据库,它在JTable和输入掩码中的镜像

  3. 混合使用这两种方法。也许快速,单细胞更新应使用第二种方法,而INSERTDELETE s则需要第一种方法?虽然效率更高,但感觉不一致。

    • 也许不在上下文3点
    • 的背景下
  4. 还有其他办法吗?

    • 是的,有几种方法,但My GUI includes a JTable and several forms that may ...可以使简单的事情复杂化

    • 使用

      创建一个JFrame
      1. JSplitPane可能有一个区域用于CardLayout铺设的所有输入掩码,第二个用于JTable,只有一个JTable,有一个XxxTableModel(您可以在JList中添加StandindData或在南部或西部/东部地区添加另一个JTable)意图填补容器中的可用空间)

      2. 使用BorderLayout,中间是CardLayout铺设的输入掩码,请参阅上述第1点的其余部分。

      3. 将一些JTables / Lists(例如参见Bloomberg或Reuters Xtra3000的屏幕)添加到一个JFrame中,使用JMenuItems为这些对象添加JPopupMenu添加,修改,删除,修改...... JTables中的项目/列表,然后只创建一个由CardLayout布局的JDialog,并在应用程序启动时包含所有输入掩码,然后从JPopupMenu输出将包含三个代码行切换到基于源的卡,JDialog的调用包,调用JDialog的setVisible(true) ,但必须包装到invokeLater,

      4. 在调用setVisible(false)之前将数据保存在数据库中后重置输入掩码中的所有JComponents,否则下一个可见性可以使用JComponent中的值闪烁/刷新

    • 没人保证来自输入掩码的数据保存在数据库中并且正确,

      1. e.g。可以有定义的触发器,填充其余列的值,然后所有数据流可以是异步的,由内部数据库规则延迟

      2. 数据流必须是将数据保存到数据库,如果PreparedStatement执行无异常,那么你可以刷新输入掩码为默认值,下一步可能是将数据加载到XxxMableModel,如果有弹出JDialog ,现在是隐藏JDialog的时刻

  5. 如果有异常,则输入掩码及其值不会发生任何事情,对用户来说更好,更安全,可以基于模拟,可以创建截图然后报告它。 ..