我正在迭代地查询一个名为txqueue的mysql表,该表正在不断增长。
每个连续查询仅考虑在上一次迭代中执行查询后插入到txqueue表中的行。
为实现此目的,每个连续查询从表中选择主键(下例中的seqno字段)超过上一个查询中观察到的最大seqno的行。
以这种方式识别的任何新插入的行都将写入csv文件。
目的是让这个过程无限期地运行。
下面的尾递归函数可以正常工作,但过了一段时间它会遇到java.lang.StackOverflowError。每个迭代查询的结果包含两到三行,每秒左右返回一次结果。
关于如何避免java.lang.StackOverflowError的任何想法?
这实际上是可以/应该通过流媒体实现的吗?
非常感谢任何建议。
这是有效的代码:
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)
}
}
答案 0 :(得分:6)
你的函数不是尾递归的(因为最后是catch
)。
这就是你最终堆栈溢出的原因。
你应该总是使用@scala.annotation.tailrec
注释你想要尾递归的函数 - 如果不能进行尾递归,它将无法编译,这样你就不会对它在运行时感到惊讶。