在函数式Scala代码中使用JDBC PreparedStatement.addBatch

在函数式Scala代码中使用JDBC PreparedStatement.addBatch,scala,jdbc,batch-processing,Scala,Jdbc,Batch Processing,我需要从一个数据库中读取数百万行,然后将它们写入另一个数据库。我想使用PreparedStatement.addBatch进行大批量写入(可能是1000行)。我不需要他们参与交易。我正在用Scala 2.9.2编写代码 一种方法如下: val sourceResultSet = ... val targetStatement = targetConnection.prepareStatement(...) var rowCount = 0 while (sourceResultSet.next(

我需要从一个数据库中读取数百万行,然后将它们写入另一个数据库。我想使用
PreparedStatement.addBatch
进行大批量写入(可能是1000行)。我不需要他们参与交易。我正在用Scala 2.9.2编写代码

一种方法如下:

val sourceResultSet = ...
val targetStatement = targetConnection.prepareStatement(...)
var rowCount = 0
while (sourceResultSet.next()) {
  // Read values from sourceResultSet and write them to targetStatement
  targetStatement.addBatch()
  rowCount += 1
  if (rowCount % 1000 == 0) {
    targetStatement.executeBatch()
    rowCount = 0
  }
}

如何以更实用的方式实现这一点,而不使用
var rowCount
?我还需要考虑RAM的使用情况;我正在读取数百万行,因此任何涉及同时将所有源行存储在内存中的解决方案都将失败。

源结果集的类型是什么?我根据您的使用情况假设一个迭代器/流,但无论哪种方式,您都可以使用Scala collection的
take
一次抓取1000个元素(这适用于列表、集合、迭代器、流等)。要在功能上做得更好(虽然只是副作用,所以不是纯功能性的),请定义一个内联函数:

def processSource(sourceResultSet: Iterator): Unit = {
  if(sourceResultSet.hasNext) {
    sourceResultSet.take(1000).foreach(row => /* Add to batch */)
    targetStatement.executeBatch()
    processResult(sourceResultSet) // How you handle the recursion depends on what sourceResultSet is
  }
}

val sourceResultSet = ...
val targetStatement = targetConnection.prepareStatement(...)
processSource(sourceResultSet)

只要sourceResultSet是惰性的(流或迭代器),这将避免立即将其加载到内存中。

我假设上面有一个迭代器,当读取一个值时,它会自动向前移动迭代器。请注意,在对迭代器进行处理后,应该认为原始迭代器无效。在将原始结果集转换为迭代器后,最好使用“分组”方法进行批处理:
for(batch@Andrew:It实际上是一个java.sql.ResultSet,但我有一个隐式方法将其转换为流(另一个用于迭代器)。谢谢。