Scala:通过生成器(可迭代)公开 JDBC ResultSet

Posted

技术标签:

【中文标题】Scala:通过生成器(可迭代)公开 JDBC ResultSet【英文标题】:Scala: Exposing a JDBC ResultSet through a generator (iterable) 【发布时间】:2011-01-07 08:13:04 【问题描述】:

我在数据库中有一组行,我想提供一个界面来像这样旋转它们:

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

有没有办法可以将其转换为不将整个集合存储在内存中?也许我可以使用 for 理解?

【问题讨论】:

【参考方案1】:

实现相同目的的更简单(惯用)方法是

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

您需要 .toList 来强制评估,否则基础集合将是一个流,并且 ResultSet 可能会在评估发生之前关闭。

【讨论】:

【参考方案2】:

我遇到了同样的问题,基于上面的想法,我通过简单地编写一个适配器类创建了以下解决方案:

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。

【讨论】:

我使用了这个解决方案。非常感谢!我确实必须调用 toList 才能使用结果。 val externalKeys = resultSet.map x => x.getString("external_key") .toList 这有问题。根据 hasNext 的规范,它应该在不推进结果集的情况下执行。因此,@Rex Kerr 建议的缓存或使用 isLast (不确定性能)是一个更好的选择。【参考方案3】:

尝试扩展迭代器。我还没有测试过,但是是这样的:

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

这应该在被调用时存储 rs,否则只是对 rs 调用的轻包装。

如果要保存遍历的值,请查看 Stream。

【讨论】:

我只是假设 rs 实际上有一个“hasNext”方法。如果没有,您应该在迭代器中使用(可能是私有的)var 缓存下一个结果,并让 hasNext 说明该缓存结果是否存在。 是的,这行得通,我使用了 hasNext = rs.isLast。一个麻烦是虽然我没有任何机制来关闭 rs 和连接。在我当前的代码中,我将(上面的)代码包装在一个“使用”方法中,它为我关闭了东西。 如果“isLast”意味着您无法获得另一个,我认为 hasNext = !rs.isLast 将是要做的事情。也许只是一个错字? @Rex 哎呀,是的,我的意思是 hasNext = !rs.isLast

以上是关于Scala:通过生成器(可迭代)公开 JDBC ResultSet的主要内容,如果未能解决你的问题,请参考以下文章

python迭代器

Python教程·迭代可迭代对象迭代器与生成器详解

迭代器和生成器

梯度迭代树(GBDT)算法原理及Spark MLlib调用实例(Scala/Java/python)

构成可迭代对象的要素

迭代器可迭代对象与生成器