复制Java ResultSet

8
我有一个java.sql.ResultSet对象需要更新,但是结果集不可更新。不幸的是,这是我使用的特定框架的限制。
我的目标是从数据库中获取数据,然后操作一小部分数据,并将数据写入CSV文件。在这个阶段,我认为最好的选择是创建一个新的结果集对象,并将原始结果集的内容复制到新的结果集中,同时操作数据。
然而,我在谷歌上搜寻了很久,似乎无法确定如何做到这一点,或者是否可能。我对Java一切都很陌生,所以任何帮助都将不胜感激。

一个严格实现ResultSet接口的类不会保存任何数据。驱动程序可以在每个“next()”时返回到数据库。这就是为什么ResultSet通常既不可序列化也不可克隆的原因。几乎所有人都会将结果读入其他数据结构中(2D数组,数组向量,映射列表等)。如果您愿意,可以使该数据结构可序列化或可克隆。 - david blaine
2个回答

11

感谢您的回复。最终我找到了CachedRowSet,这正是我需要的。使用它,我能够断开ResultSet对象并更新它。

更重要的是,因为CachedRowSet实现了ResultSet接口,我仍然可以将它传递给我的文件生成方法,该方法需要一个实现ResultSet接口的对象。


谢谢!正在寻找这个。 - Ali Akbar

10

通常的做法是将ResultSet映射到一个List<Entity>,其中Entity是您自己定义的类,包含有关单个数据库行所表示数据的信息。例如,UserPersonAddressProductOrder等,具体取决于表格中实际包含的内容。

List<Entity> entities = new ArrayList<Entity>();
// ...
while (resultSet.next()) {
    Entity entity = new Entity();
    entity.setId(resultSet.getLong("id"));
    entity.setName(resultSet.getString("name"));
    entity.setValue(resultSet.getInt("value"));
    // ...
    entities.add(entity);
}
// ...
return entities;

然后,您可以按照通常的Java方式访问、遍历和修改它。最后,在将其存储回DB时,请使用PreparedStatement一次性批量更新。

String sql = "UPDATE entity SET name = ?, value = ? WHERE id = ?";
// ...
statement = connection.prepareStatement(sql);
for (Entity entity : entities) {
    statement.setString(1, entity.getName());
    statement.setInt(2, entity.getValue());
    statement.setLong(3, entity.getId());
    // ...
    statement.addBatch();
}
statement.executeBatch();
// ...

需要注意的是,一些数据库对批处理大小有限制。Oracle的JDBC驱动程序限制在大约1000项上。因此,您可能希望每1000个项目调用executeBatch()一次。使用循环内部的计数器应该很简单。

另请参阅:


嗨,感谢您的热情回复。在这种情况下,数据将从数据库中提取,进行少量处理,然后将数据写入CSV文件。 - Peanut
如果操作是基于行的,那么就在while循环内部执行,并立即将其作为CSV文件的新行写入。顺便说一句,平均DB都配备有CSV导出工具,可以比您在Java中做得更有效率。不清楚您使用的是哪个,这里只举一个基于MySQL的例子:LOAD DATA INFILE - BalusC
@BalusC - 如果您可以访问一个ETL工具,使用它来完成这样的任务会更好,不是吗? - david blaine

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接