【发布时间】:2008-10-29 10:53:09
【问题描述】:
这个问题很基本。我有一个 JTable 显示来自数据库的缓存数据。如果用户单击单元格进行编辑,我想尝试锁定数据库中的该行。如果锁定不成功,我想阻止编辑。
但我似乎找不到任何干净的方法来完成此操作。我错过了什么吗?
【问题讨论】:
这个问题很基本。我有一个 JTable 显示来自数据库的缓存数据。如果用户单击单元格进行编辑,我想尝试锁定数据库中的该行。如果锁定不成功,我想阻止编辑。
但我似乎找不到任何干净的方法来完成此操作。我错过了什么吗?
【问题讨论】:
在编辑/设置值之前,表格模型通过 TableModel.isCellEditable(row,col) 询问此单元格是否可编辑。在这里你可以实现你的锁。在 TableModel.setValue(row,col,val) 之后,您应该解锁它。但。锁定操作应该会花费大量时间,并使您的 UI 不负责任。而且它很糟糕。尝试不同的方法。懒惰失败怎么办?您锁定该行,检查数据的有效性,如果数据较新则失败。如果数据没问题,你就把它们放下。解锁。
【讨论】:
Oracle 有一个很好的方法来处理这个问题,但我不知道它是否普遍适用。
在 Oracle 中,您可以在 SELECT 语句上使用 FOR UPDATE 在读取记录时锁定它。
例如,如果您要获取一行进行显示:
select * into v_row from my_table where my_table_id = 1
for update;
这将允许读取但阻止更新。如果另一个事务有锁,您的事务将等待它变得可用(或最终超时)。如果您希望语句在尝试锁定时引发异常,请添加 NOWAIT。
select * into v_row from my_table where my_table_id = 1
for update nowait;
如果该行已被锁定,您将获得:
ORA-00054: resource busy and acquire with NOWAIT specified.
希望对您有所帮助。
【讨论】:
因为您必须在点击上进行测试,所以您不能使用模型的方式来执行此操作,因此您应该尝试覆盖 JTable 的 public void changeSelection(int rowIndex, int columnIndex, boolean toggle, oolean extend) 方法。如果该行被锁定,则不要调用 super.changeSelection,它应该使该行保持未选中状态。
【讨论】:
相反,您可以等到用户实际更改某些内容,然后覆盖 JTable.editingStopped 以在那里完成工作(您甚至可以检查值是否已更改)
这样在用户实际更改某些内容之前不会进行锁定。
【讨论】: