1

我的 GUI 包括一个和JTable几个可能触发INSERT或SQL 查询的表单。每当发生这种情况时,我都希望我的表格能够相应地更新。由于必须更新和远程 SQL 表,因此有几种方法可以继续。UPDATEDELETETableModel

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

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

  • 混合这两种方法。也许快速的单单元更新应该使用第二种方法,而INSERTs 和DELETEs 需要第一种?虽然效率更高,但感觉不一致。

  • 还有其他方法吗?

我应该如何进行?请分享您在这件事上的经验。

4

3 回答 3

1

我喜欢您JTable使用SELECT.

如果您担心 0.5-1 秒的暂停 - 您可以按以下方式混合第一个和第二个变体:立即使用“预期”结果更新表,执行 SQL,然后SELECT修改数据并检查它是否与当前相同。我认为在大多数情况下它们将是相同的,因此不需要更新JTable,但您也可以获得同步模型。

于 2013-06-13T10:04:08.863 回答
1
  1. 首先更新 SQL 表,然后SELECT是修改后的数据,并TableModel使用返回的ResultSet. 这就是我目前正在做的事情。它保证了表和数据库的完美同步。但是,TableModel直到从 中提取其数据后才会更新ResultSet,在我的情况下,整个过程平均需要 0.5 到 1 秒。这不是太糟糕,但也不是太好。

    • 错误的想法创建一个新的 XxxTableModel 不仅适得其反,一个 XxxTableModel 可用于所有视图,对于一些 JTables/JLists 仅在没有使用 RowSorter 或 RowFilter 的情况下注意,然后代码中的逻辑必须包含过滤基于一个 XxxTableModel 对所有 JTable 进行排序

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

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

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

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

  3. 混合这两种方法。也许快速的单单元更新应该使用第二种方法,而INSERTs 和DELETEs 需要第一种?虽然效率更高,但感觉不一致。

    • 也许不是在上午 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,为这些对象添加 JPopupMenu,使用 JMenuItems 添加、修改、删除、修改 .... JTables/Lists 中的项目,然后仅创建一个由 CardLayout 铺设的 JDialog,并在应用程序启动时包含所有输入掩码,然后从 JPopupMenu 输出将包含三行代码行根据源切换到卡,为 JDialog 调用 pack,为 JDialog 调用 setVisible(true),但必须包装到调用以后,

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

    • 没有人保证输入掩码中的数据正确保存在数据库中,

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

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

  5. 如果有异常,那么输入掩码及其值不会发生任何事情,对用户来说更好更安全,可以在此基础上进行模拟,可以创建屏幕截图然后报告它....

于 2013-06-13T10:37:21.543 回答
1

The first approach that came to my mind is to create a subclass of AbstractTableModel, and store the data in its private ArrayList<?> field. In its constructor, query the database with the data you want to show in the table.

If a row is added to the table, an INSERT statement with the data inserted will be fired to the DB.

If an update to a cell in the table is done, validate if the update is possible. If possible, an UPDATE will be fired to the DB

If a row is deleted, a DELETE FROM statement will be fired to the DB.

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
    }
}
于 2013-06-13T10:09:09.960 回答