我们公司编写了一个相当复杂的程序来将数据从一个数据库传输到另一个数据库。应该传输的数据在特定列中用“1”(String/Varchar2)标记。 我无法解释为什么这不仅仅是一个数字或 boolean 字段。我想这是一个历史遗迹。
ResultSet
是这样创建的:
Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
ResultSet extractedData = stmt.executeQuery(sql);
如果找到什么东西,将它提取到一个文件中:
if (extractedData.next()) {
writeDataToFile(extractedData)
}
简化的写法是这样的:
private void writeDataToFile(ResultSet extractedData) {
extractedData.beforeFirst(); // because of the next() we called before
writeLines(extractedData);
}
在 writeLines()
中,我们遍历整个 ResultSet
并将其写入文件。
完成后,我们可以通过将列中的值设置为“0”来将数据标记为已传输。万一发生异常,我们不能提前做。
extractedData.beforeFirst();
while (extractedData.next()) {
extractedData.updateString(updateColumn, "0");
extractedData.updateRow();
}
我们怀疑 updateRow()
导致 SQLException
并显示消息“发生值冲突”
这种情况很少发生。每个月都会提取数百万条记录,其中只有大约 2 条抛出此错误。
有人知道是什么原因造成的吗?
最佳答案
ResultSet 没有在表行上建立任何锁。另一个过程可以改变它。 oracle中rowid发生异常时会出现异常。
如何复制此行为。
create table example1 (id number, value varchar2(10));
insert into example1 values(1,'a');
insert into example1 values(2,'b');
insert into example1 values(3,'c');
insert into example1 values(4,'d');
insert into example1 values(5,'e');
commit;
还有java APP。 deleteRow - 打开新的 oracle session 并从表中删除行。
public class Updatable {
public static void main(String[] args) throws SQLException, Exception {
Connection conn = ConnectionDefinition.getOracleConnection();
Statement createStatement = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
ResultSet executeQuery = createStatement.executeQuery("select id, value from example1");
while (executeQuery.next()) {
int id = executeQuery.getInt("id");
System.out.println("id " + executeQuery.getString("id") + " value " + executeQuery.getString("value"));
if (id == 3) {
deleteRow();
Thread.sleep(5000);
executeQuery.updateString("VALUE", "new value");
executeQuery.updateRow();
}
}
conn.close();
}
public static void deleteRow(){
Runnable r = new Runnable() {
@Override
public void run() {
try {
Connection conn = ConnectionDefinition.getOracleConnection();
PreparedStatement st = conn.prepareStatement("delete from example1 where id = 3");
st.execute();
st.close();
} catch (Exception ex) {
ex.getStackTrace();
}
}
};
Thread th = new Thread(r);
th.start();
}
}
为避免此类冲突,请在运行查询时使用 Oracle FOR UPDATE 功能。
ResultSet executeQuery = createStatement.executeQuery("select id, value from example1 for update");
关于java - 更新 ResultSet 中的行会生成错误 : 'Value conflicts occurs' ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33918347/