2

我想将数据库表显示为 JTable。我以前从未使用过 JTable,所以我搜索了 JTable 和 TableModel。

通过谷歌搜索,我可以编写自己的自定义 TableModel 来显示存储在

Object[][] data;

现在,我想将我的数据库表数据显示到 JTable 中。我也进行了搜索,并对此有所了解,但仍然对 AbstractTableModel 的实现类中应该去哪里感到困惑。

以下是自定义 TableModel 的代码。

public abstract class AbstractPOLDATTableModel extends AbstractTableModel {
protected boolean DEBUG = false;
private String[] columnNames;
private Object[][] data;

protected AbstractPOLDATTableModel(String[] columnNames, Object[][] data) {
    this.columnNames = columnNames;
    this.data = data;
}

public int getColumnCount() {
    return columnNames.length;
}

public int getRowCount() {
    return data.length;
}

@Override
public String getColumnName(int col) {
    return columnNames[col];
}

public Object getValueAt(int row, int col) {
    return data[row][col];
}

@Override
public Class getColumnClass(int c) {
    return getValueAt(0, c).getClass();
}

@Override
public boolean isCellEditable(int row, int col) {
    if (col < 2) {
        return false;
    } else {
        return true;
    }
}

@Override
public void setValueAt(Object value, int row, int col) {
    if (DEBUG) {
        System.out.println("Setting value at " + row + "," + col
                           + " to " + value
                           + " (an instance of "
                           + value.getClass() + ")");
    }

    data[row][col] = value;
    fireTableCellUpdated(row, col);

    if (DEBUG) {
        System.out.println("New value of data:");
        printDebugData();
    }
}

private void printDebugData() {
    int numRows = getRowCount();
    int numCols = getColumnCount();

    for (int i=0; i < numRows; i++) {
        System.out.print("    row " + i + ":");
        for (int j=0; j < numCols; j++) {
            System.out.print("  " + data[i][j]);
        }
        System.out.println();
    }
    System.out.println("--------------------------");
}
}

现在,如何更改上面的代码,以便我的 JTable 可以具有以下功能:

  1. 它显示来自数据库的数据
  2. 用户可以直接编辑表格,当他点击“保存”按钮时,更改会反映在数据库数据中
  3. 用户可以直接插入数据。
  4. 用户可以直接删除数据。
4

1 回答 1

1

我假设您已经根据 Adamski 在上一个问题中的建议实施了 1 。此外,根据 Sanoj 的建议,更改为使用某种列表来存储您的数据。

  1. 要支持 2-4,您必须确保从数据库中提取的数据仅来自一个表且不涉及派生数据(例如聚合、column1 + column2)。where如果您打算让用户过滤行,则需要跟踪您的子句。

  2. 在每一行中,存储另一个表示用户使用 GUI 进行的更新的行(我们称之为 updatedRow)。对行进行任何更新后,需要使用包含更新数据的新行填充此字段。单击“保存”后,您将对具有非空 updatedRow 的所有行运行更新查询,使用 updatedRow 中与原始行中的数据不匹配的数据更新数据库(如果用户将数据更改回它最初是)。您可能还有另一个“撤消更新”按钮,它使用非空 updatedRow 的所有行的原始数据填充表。

    我强烈建议您在构成主键的字段上存储额外的元数据并防止这些字段被更改,因为对这些列的更新可能很昂贵(因为它们可能已被索引并且可能附加了一些 RI 约束)。这应该通过使此类列不可编辑来反映在 GUI 中。更新中的where子句将仅使用这些字段而不是所有字段(您仍然需要用户在 1 中设置的其他过滤器)。

  3. 我建议一个两步过程。用户首先单击向表中添加一行的按钮。输入数据后,用户单击另一个按钮以插入数据库(或者您可以将此功能与“保存”按钮中的更新结合起来)。如果主键列不是某个自动生成的 ID,您将需要允许主键字段可编辑新插入的行。

    为了区分哪些行已经在数据库中,哪些行不在,我建议存储一个新插入的行列表。

    如果您让用户只选择要在表中显示的某些列,您将需要确定如何处理未显示的列(例如,让数据库设置默认值,使用自动生成的 ID 填充)。

  4. 最好通过在每行上设置一个复选框来实现这一点,然后当单击“删除”按钮时,它会调用 SQL 使用 1 中的过滤器和 2 中提到的主键元数据删除每个选中的行,并删除它从表。

一般考虑:

  • 相同的 setValueAt 方法将用于更新和插入的行,但您需要不同的行为。您想设置 updatedRow 进行更新,但不是在编辑您要插入的行时。

  • 您将如何处理诸如未满足约束或无效输入(例如数字字段中的“abcde”)之类的错误?

  • SQL注入。

于 2010-02-04T23:37:49.603 回答