java – 更新ResultSet中的行会生成错误:’发生值冲突’

我们公司编写了一个相当复杂的程序来将数据从一个数据库传输到另一个应该传输的数据在某列中用’1′(String / Varchar2)标记.

我无法解释为什么这不仅仅是数字或布尔字段.我想这是一个历史遗迹.

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会话并从表中删除行.

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,example1 for update for update”);

点赞