Java 使用PreparedSelect语句时更新数据库
我正在使用Java 使用PreparedSelect语句时更新数据库,java,prepared-statement,Java,Prepared Statement,我正在使用PreparedStatement从MS SQL数据库中选择数据的子集。 在遍历resultset时,我还想更新行。现在我用的是这样的东西: prepStatement = con.prepareStatement( selectQuery, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE); rs
PreparedStatement
从MS SQL数据库中选择数据的子集。
在遍历resultset时,我还想更新行。现在我用的是这样的东西:
prepStatement = con.prepareStatement(
selectQuery,
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_UPDATABLE);
rs = prepStatement.executeQuery();
while(rs.next){
rs.updateInt("number", 20)
rs.updateRow();
}
数据库已更新为正确的值,但出现以下异常:
Optimistic concurrency check failed. The row was modified outside of this cursor.
我已经在谷歌上搜索过了,但在这个问题上找不到任何帮助
如何防止此异常?或者,由于程序确实执行了我希望它执行的操作,我可以忽略它吗?从数据库(通过光标)检索记录到您尝试将其保存回来的那一刻,记录已被修改。如果
number
列可以安全地独立于记录的其余部分进行更新,或者独立于已经将number
列设置为其他值的其他进程进行更新,则您可能会尝试执行以下操作:
con.execute("update table set number = 20 where id=" & rs("id") )
但是,竞争条件持续存在,您的更改可能会被另一个进程覆盖
最好的策略是忽略异常(记录未更新),可能将失败的记录推送到队列(内存中),然后对失败的记录进行第二次传递(重新评估
query
中的条件,并根据需要进行更新-将number 20
添加为query
中的条件之一,如果情况并非如此。)重复操作,直到没有更多记录失败。最终将更新所有记录。假设您确切知道要更新的行,我会这样做
- 将自动提交设置为关闭
- 将隔离级别设置为可序列化
- 从更新条件所在的表中选择行1,行1
- 更新行
- 承诺
这是通过悲观锁定实现的(假设您的数据库中支持行锁定,它应该可以工作)您能告诉我们正在使用哪个事务隔离级别吗?…以及您更新的确切查询和确切列是什么吗?可能是“其他人”吗是谁触发了您这边的Optimistic lock异常,并实际执行了您看到的更新?:)不,更新只发生在一个地方,我的进程是唯一访问数据库的进程啊!这只能意味着您的查询返回重复的记录,第一次更新很好,第二次失败。:)为什么会这样?