在函数式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,但我有一个隐式方法将其转换为流(另一个用于迭代器)。谢谢。