Когато трябва да прочета милиони редове от база данни от база данни на PostgreSQL, използвайки JDBC драйвера, винаги използвам курсор, в противен случай ще получа OutOfMemoryError. Ето шаблона (псевдокод), който използвам:
begin transaction
execute("declare cursor...")
while (true) {
boolean processedSomeRows = false
resultSet = executeQuery("fetch forward...")
while (resultSet.next()) {
processedSomeRows = true
...
}
if (!processedSomeRows) break
}
close cursor
commit
Това е по-„функционален“ еквивалент, който измислих, за да бъде внедрен в Scala:
begin transaction
execute("declare cursor...")
@tailrec
def loop(resultSet: ResultSet,
processed: Boolean): Boolean = {
if (!resultSet.next()) processed
else {
// Process current result set row
loop(resultSet, true)
}
}
while (loop(executeQuery("fetch forward..."), false))
; //Empty loop
close cursor
commit
Знам, че това е измислено, но има ли по-добър начин, без да се прибягва до променливост? Ако се опитвах да направя това в Haskell, можех да измисля решение, което включва монади, но не искам да изпращам ума си в тези „изкривени малки пасажи, всички еднакви“, защото може никога да не се върне...
Iterator
s илиStream
s за обработка наResultSet
s, но не мога да измисля начин да спра итерацията (processed
аргумент по-горе). - person Ralph   schedule 09.10.2012takeWhile
), за да видя дали мога да прекратя външнияwhile
цикъл. - person Ralph   schedule 09.10.2012