Scala 尾递归 java.lang.StackOverflowError

Scala Tail Recursion java.lang.StackOverflowError

我正在迭代查询一个名为 txqueue 的 mysql table,它正在不断增长。

每个后续查询仅考虑在上一次迭代中执行查询后插入到 txqueue table 中的行。

为了实现这一点,每个连续的查询都从 table 中选择行,其中主键(我下面示例中的 seqno 字段)超过了上一个查询中观察到的最大 seqno。

以这种方式识别的任何新插入的行都将写入 csv 文件。

此过程的目的是无限期地运行。

下面的尾递归函数工作正常,但过了一会儿它 运行 变成了 java.lang.WhosebugError。每次迭代查询的结果包含两到三行,并且大约每秒返回一次结果。

关于如何避免 java.lang.WhosebugError 的任何想法?

这实际上是 can/should 通过流媒体实现的吗?

非常感谢您的任何建议。

这是可以使用一段时间的代码:

object TXQImport {

  val driver = "com.mysql.jdbc.Driver"
  val url = "jdbc:mysql://mysqlserveraddress/mysqldb"
  val username = "username"
  val password = "password"
  var connection:Connection = null

  def txImportLoop(startID : BigDecimal) : Unit = {

      try {

        Class.forName(driver)
        connection = DriverManager.getConnection(url, username, password)
        val statement = connection.createStatement()
        val newMaxID = statement.executeQuery("SELECT max(seqno) as maxid from txqueue")

        val maxid = new Iterator[BigDecimal] {
          def hasNext = newMaxID.next()
          def next() = newMaxID.getBigDecimal(1)
        }.toStream.max

        val selectStatement = statement.executeQuery("SELECT seqno,someotherfield " +
          " from txqueue where seqno >= " + startID + " and seqno < " + maxid)

        if(startID != maxid) {

          val ts = System.currentTimeMillis
          val file = new java.io.File("F:\txqueue " + ts + ".txt")
          val bw = new BufferedWriter(new FileWriter(file))

          // Iterate Over ResultSet
          while (selectStatement.next()) {

            bw.write(selectStatement.getString(1) + "," + selectStatement.getString(2))
            bw.newLine()

          }

          bw.close()

        }

        connection.close()
        txImportLoop(maxid)

      }

      catch {
        case e => e.printStackTrace
      }  

  }

  def main(args: Array[String]) {

    txImportLoop(0)

  }

}

你的函数不是尾递归的(因为最后的 catch)。 这就是为什么你最终会出现堆栈溢出的原因。

你应该总是用 @scala.annotation.tailrec 注释你打算尾递归的函数 - 如果尾递归是不可能的,它会编译失败,这样你就不会在 [=16 时对它感到惊讶=]时间。