You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将CachedRowSet中多行修改保存到数据库?

问题:CachedRowSet批量更新记录无法同步到数据库

我正在编写一个更新CachedRowSet中记录的程序,但目前仅能保存单条记录的修改。当CachedRowSet包含多条记录时,遍历修改后无法将变更同步到数据库。

我能正常从数据库获取数据,使用CachedRowSet是为了实现断开连接模式,以支持大量用户访问避免应用卡顿。我了解PreparedStatement可防范SQL注入,但该程序仅我个人使用。

以下代码用于将主表的新ID更新到子表的外键字段:原制造系统未使用自增ID,采用字符型ID,现在要改为自增ID,需批量更新子表外键。

private void FillForeignKey(String strDeprecated_Id_Column, String strChild_Table_Name, String strChildForeignKey_Column,
                            Integer intNewMaster_Id, String strOldMaster_Id) throws SQLException {

     try {
        Connection connection = getConnection("jdbc:mysql://127.0.0.1:5222/jobtrack", "root", "");
        //Select Master table with

        String seqlChild = "SELECT " + strDeprecated_Id_Column + ", " + strChildForeignKey_Column +
                " FROM " + strChild_Table_Name +
                " Where " + strDeprecated_Id_Column +" = " +  "'" + strOldMaster_Id + "'";
        System.out.println(seqlChild);

        Statement stChild = connection.createStatement();
        ResultSet rsChild = stChild.executeQuery(seqlChild);
        RowSetFactory factory = RowSetProvider.newFactory();
        CachedRowSet crsetChild = factory.createCachedRowSet();
        crsetChild.populate(rsChild);
        rsChild.close();
        //connection.close();
        connection.setAutoCommit(false);

        System.out.println("Child Rowset Size " + crsetChild.size());
        System.out.println("New Id " + intNewMaster_Id);
        System.out.println("Old Id " + strOldMaster_Id);

        while (crsetChild.next()) {

            crsetChild.updateInt(strChildForeignKey_Column, intNewMaster_Id);
            crsetChild.moveToCurrentRow();
            System.out.println("Data From child Rowset " + crsetChild.getInt(strChildForeignKey_Column));
            crsetChild.updateRow();
            crsetChild.acceptChanges(connection);
        }

        crsetChild.close();
            //connection.close();

    }catch (SQLException e) {
        System.out.println(e.getMessage());

    }
}

解决方案

核心问题是每次循环内调用acceptChanges(connection):该方法会立即同步当前所有变更到数据库,并重置CachedRowSet的变更标记。第一次同步后,后续修改的记录因标记被清空,无法再次触发同步。

修改后的代码将同步操作移到循环外,同时优化资源管理和事务控制:

private void FillForeignKey(String strDeprecated_Id_Column, String strChild_Table_Name, String strChildForeignKey_Column,
                            Integer intNewMaster_Id, String strOldMaster_Id) throws SQLException {
    // try-with-resources自动管理资源,避免泄漏
    try (Connection connection = getConnection("jdbc:mysql://127.0.0.1:5222/jobtrack", "root", "");
         Statement stChild = connection.createStatement()) {

        String sqlChild = "SELECT " + strDeprecated_Id_Column + ", " + strChildForeignKey_Column +
                " FROM " + strChild_Table_Name +
                " WHERE " + strDeprecated_Id_Column + " = '" + strOldMaster_Id + "'";
        System.out.println(sqlChild);

        try (ResultSet rsChild = stChild.executeQuery(sqlChild)) {
            RowSetFactory factory = RowSetProvider.newFactory();
            CachedRowSet crsetChild = factory.createCachedRowSet();
            crsetChild.populate(rsChild);

            System.out.println("Child Rowset Size " + crsetChild.size());
            System.out.println("New Id " + intNewMaster_Id);
            System.out.println("Old Id " + strOldMaster_Id);

            // 遍历标记所有需要修改的行
            while (crsetChild.next()) {
                crsetChild.updateInt(strChildForeignKey_Column, intNewMaster_Id);
                System.out.println("Data From child Rowset " + crsetChild.getInt(strChildForeignKey_Column));
                crsetChild.updateRow(); // 标记当前行已修改
            }

            // 所有行修改完成后,一次性同步到数据库
            connection.setAutoCommit(false);
            crsetChild.acceptChanges(connection);
            connection.commit();

            crsetChild.close();
        } catch (SQLException e) {
            connection.rollback(); // 异常时回滚事务
            System.out.println(e.getMessage());
            throw e;
        }
    } catch (SQLException e) {
        System.out.println(e.getMessage());
    }
}
关键修改说明
  1. 批量同步变更:将acceptChanges(connection)移到循环外,让CachedRowSet收集所有修改后一次性提交,避免每次同步重置变更标记。
  2. 自动资源管理:使用try-with-resources语法,自动关闭Connection、Statement、ResultSet,无需手动调用close()。
  3. 事务控制:开启手动提交模式,同步完成后手动提交,异常时回滚,保证数据一致性。
  4. 移除冗余代码:删除moveToCurrentRow(),next()已经定位到当前行,修改后直接调用updateRow()即可标记变更。

内容的提问来源于stack exchange,提问作者Rocco Szabo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 13:43:11