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

Java 使用SQL时,我应该如何处理TableModel更新?,java,sql,swing,jtable,Java,Sql,Swing,Jtable,我的GUI包括一个JTable和几个表单,这些表单可能触发INSERT、UPDATE或DELETESQL查询。无论何时发生,我都希望我的表得到相应的更新。由于必须更新TableModel和远程SQL表,因此有几种方法可以继续 首先更新SQL表,然后选择修改后的数据,并调用fireTableDataChanged()这就是我目前正在做的事情。它保证表和数据库完全同步。然而,TableModel在从ResultSet提取数据之前不会更新,在我的例子中,整个过程平均需要0.5到1秒。这不算太坏,但也

我的GUI包括一个
JTable
和几个表单,这些表单可能触发
INSERT
UPDATE
DELETE
SQL查询。无论何时发生,我都希望我的表得到相应的更新。由于必须更新
TableModel
和远程SQL表,因此有几种方法可以继续

  • 首先更新SQL表,然后
    选择修改后的数据,并调用
    fireTableDataChanged()
    这就是我目前正在做的事情。它保证表和数据库完全同步。然而,
    TableModel
    在从
    ResultSet
    提取数据之前不会更新,在我的例子中,整个过程平均需要0.5到1秒。这不算太坏,但也不算太好

  • 同时更新它们,修改
    TableModel
    ,使之与我期望的上一个方法相匹配。
    这可以提高客户端的性能,因为更改几乎是即时的,SQL内容将“在后台”运行。但是我不确定是否会丢失表和数据库之间的同步,这看起来像是肮脏的方式

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

  • 还有别的办法吗?


我应该如何进行?请分享您在这方面的经验。

我喜欢您使用
SELECT
从SQL表更新
JTable
的第一选择


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

我想到的第一种方法是创建
AbstractTableModel
的子类,并将数据存储在其私有
ArrayList
字段中。在其构造函数中,使用要在表中显示的数据查询数据库

如果向表中添加了一行,则将向数据库激发一条插入了数据的
INSERT
语句

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
    }
}
如果对表中的单元格进行了更新,请验证更新是否可行。如果可能,将向数据库触发
更新

如果删除了一行,则会向数据库激发一条
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
    }
}
公共类MyTableModel扩展了AbstractTableModel{
私有列表数据源;
公共MyTableModel(){
dataSource=新的ArrayList();
//查询数据库,然后将查询的数据添加到数据源,
//您应该在后台使用SwingWorker进行此操作
//使用正确的参数调用fireTableRowsInserted
}
@凌驾
public int getColumnCount(){
返回3;
}
@凌驾
public int getRowCount(){
返回dataSource.size();
}
@凌驾
公共对象getValueAt(整数行,整数列){
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.getocculation();
返回返回;
}
@凌驾
public void setValueAt(对象值、整行、整列){
//验证是否可以进行更新,如果可以,请继续
//更新数据库中的值
//更新arraylist中的值
//调用super.setValueAt(value,row,col);
}
公共无效地址行(p人){
//验证此人是否可插入,如果是,则继续
//将此人插入数据库
//将此人添加到arraylist
//调用fireTableRowsInserted
}
公共void deleteRow(int行){
//调用fireTableRowsDeleted
}
}
  • 首先更新SQL表,然后
    选择修改后的数据,并使用返回的
    结果集创建一个新的
    TableModel
    ,这就是我目前正在做的事情。它保证表和数据库完全同步。然而,
    TableModel
    在从
    ResultSet
    提取数据之前不会更新,在我的例子中,整个过程平均需要0.5到1秒。这不算太坏,但也不算太好

    • 错误的想法创建一个新的XxxTableModel不仅适得其反,一个XxxTableModel可以用于所有视图,对于一些JTables/jlist,只有在没有使用RowSorter或RowFilter的情况下,才需要注意,那么代码中的逻辑必须包含基于一个XxxTableModel的所有jtable的过滤排序

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

  • 同时更新它们,修改
    TableModel
    ,使之与我期望的上一个方法相匹配。
    这可以提高客户端的性能,因为更改几乎是即时的,SQL内容将“在后台”运行。但是我不确定是否会丢失表和数据库之间的同步,这看起来像是肮脏的方式

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

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

  • 将这两种方法混合使用。也许快速的单单元格更新应该使用第二种方法,而
    插入
    s和
    删除
    s