Scala: предоставление JDBC ResultSet через генератор (повторяемый) - PullRequest
14 голосов
/ 20 января 2010

У меня есть набор строк в базе данных, и я хотел бы предоставить интерфейс для их прокрутки следующим образом:

def findAll: Iterable[MyObject]

Там, где нам не требуется иметь все экземпляры в памяти одновременно. В C # вы можете легко создавать генераторы, подобные этому, с помощью yield, компилятор заботится о преобразовании кода, который проходит через набор записей, в итератор (своего рода инвертирование).

Мой текущий код выглядит так:

def findAll: List[MyObject] = {
  val rs = getRs
  val values = new ListBuffer[MyObject]
  while ( rs.next() ) 
    values += new valueFromResultSet(rs)
  values.toList
}

Есть ли способ, которым я мог бы преобразовать это, чтобы не хранить весь набор в памяти? Возможно, я мог бы использовать для понимания?

Ответы [ 3 ]

13 голосов
/ 11 апреля 2013

Я столкнулся с той же проблемой и, основываясь на приведенных выше идеях, создал следующее решение, просто написав класс адаптера:

class RsIterator(rs: ResultSet) extends Iterator[ResultSet] {
    def hasNext: Boolean = rs.next()
    def next(): ResultSet = rs
}

С этим вы можете, например, выполнить map операций над набором результатов - что было моим личным намерением:

val x = new RsIterator(resultSet).map(x => {
    (x.getString("column1"), x.getInt("column2"))
})

Добавить .toList для принудительной оценки. Это полезно, если соединение с базой данных закрыто перед использованием значений. В противном случае вы получите сообщение об ошибке, в котором говорится, что вы не можете получить доступ к ResultSet после закрытия соединения.

13 голосов
/ 20 января 2010

Попробуйте вместо этого расширить итератор. Я не проверял это, но что-то вроде этого:

def findAll: Iterator[MyObject] = new Iterator[MyObject] {
  val rs = getRs
  override def hasNext = rs.hasNext
  override def next = new valueFromResultSet(rs.next)
}

Это должно хранить rs при вызове, а в противном случае просто быть легкой оболочкой для вызовов rs.

Если вы хотите сохранить значения, которые вы просматриваете, посмотрите Поток.

6 голосов
/ 10 ноября 2014

Более простой (идиоматический) способ добиться того же:

Iterator.continually((rs.next(), rs)).takeWhile(_._1).map(r => valueFromResultSet(r._2)).toList

Вам нужно .toList для принудительной оценки, в противном случае базовая коллекция будет потоком, и ResultSet может быть закрыт до проведения оценки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...