java - 更新 ResultSet 中的行会生成错误 : 'Value conflicts occurs'

标签 java oracle jdbc

我们公司编写了一个相当复杂的程序来将数据从一个数据库传输到另一个数据库。应该传输的数据在特定列中用“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/

上一篇:Java分布式任务

下一篇:Java PhantomReference

相关文章:

java - 这是什么意思? (java,数据库)

sql - Oracle 合并列给出错误

java - java.library.path 中没有 ocijdbc12

java - 使用 MySQL 和 JDBC 准备语句缓存

java - 无法打开登录请求的数据库 "NitgenAccessManager"。登录失败

java - 如何找到运行 Compojure 的网络托管服务

java.lang.ClassNotFoundException : org. 代码豪斯.jackson.JsonFactory

java - JDBC 连接错误 mysql 访问被拒绝,用户 <user>@<host>

java - Spring MVC + Stomp + WebSocket + https 不作为 http

java - 为包含路径变量的 url 禁用 spring security