2016-05-24 2 views
0

J'interroge itérativement une table mysql appelée txqueue qui ne cesse de croître. Chaque requête successive considère uniquement les lignes qui ont été insérées dans la table txqueue après l'exécution de la requête dans l'itération précédenteScala Tail Recursion java.lang.StackOverflowError

Pour ce faire, chaque requête successive sélectionne des lignes de la table où la clé primaire (champ seqno dans mon exemple ci-dessous) dépasse le seqno maximum observé dans la requête précédente.

Les lignes nouvellement insérées de cette manière sont écrites dans un fichier csv.

L'intention est que ce processus s'exécute indéfiniment.

La fonction de récursion de la queue ci-dessous fonctionne correctement, mais après un certain temps, elle fonctionne dans une java.lang.StackOverflowError. Les résultats de chaque requête itérative contiennent deux à trois lignes et les résultats sont renvoyés toutes les secondes.

Des idées sur la façon d'éviter le java.lang.StackOverflowError?

Est-ce réellement quelque chose qui peut/devrait être réalisé avec le streaming?

Un grand merci pour vos suggestions.

est ici le code qui fonctionne pendant un certain temps:

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) 

    } 

} 

Répondre

6

Votre fonction n'est pas récursive (en raison de la catch à la fin). C'est pourquoi vous vous retrouvez avec un débordement de pile.

Vous devez toujours annoter les fonctions que vous avez l'intention d'être récursives avec @scala.annotation.tailrec - la compilation échouera si la récursion de la queue est impossible, de sorte que vous ne serez pas surpris par l'exécution.