2016-05-24 9 views
0

は私が繰り返し継続的に成長しているtxqueueと呼ばれるMySQLのテーブルを照会しています。Scalaの末尾再帰によってjava.lang.StackOverflowError

連続する各クエリは、前の反復において実行されたクエリの後txqueueテーブルに挿入された行を考えます。これを達成するために

、連続する各クエリは、主キー(以下私の例でSEQNOフィールド)が以前のクエリで観察された最大SEQNOを超えたテーブルから行を選択します。

このようにして新しく挿入された行は、csvファイルに書き込まれます。

このプロセスは無期限に実行されます。

末尾再帰関数は、以下の[OK]を動作しますが、しばらくするとそれがjava.lang.StackOverflowErrorをに実行されます。各反復クエリの結果には2〜3行が含まれ、結果は1秒ごとに返されます。

によって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) 

    } 

} 

答えて

6

あなたの関数は末尾再帰(なぜなら最後にcatchの)ではありません。

は、ここしばらくの間、動作するコードです。 そのため、スタックオーバーフローが発生します。

テール再帰を行う関数には常に@scala.annotation.tailrecを注釈する必要があります。つまり、実行時に尾の再帰が不可能な場合にコンパイルが失敗するため、実行時に驚くことはありません。

関連する問題