Play! で Squeryl を使用すると、奇妙な問題が発生します。
通常の使用と他のすべては完全に正常に動作します。ただし、同じリクエストで複数のトランザクションを使用すると、エラーが発生します。
それが私がSquerylをセットアップした方法です:
def initDB() {
import org.squeryl._
import play.db.DB
Class.forName("com.mysql.jdbc.Driver")
SessionFactory.concreteFactory = Some(() =>
Session.create( DB.getConnection, new MySQLAdapter) )
}
サンプル トランザクション。以下のスタック トレースでも参照されています。
transaction {
import models.Game
Game.planets.insert(planetList)
Game.moons.insert(moonList)
}
スタックトレース:
Internal Server Error (500) for request GET /generate-galaxy
Execution exception (In /app/Generator.scala around line 330)
SQLException occured : You can't operate on a closed Connection!!!
play.exceptions.JavaExecutionException: You can't operate on a closed Connection!!!
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:228)
at Invocation.HTTP Request(Play!)
Caused by: java.sql.SQLException: You can't operate on a closed Connection!!!
at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:106)
at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:65)
at org.squeryl.dsl.QueryDsl$class._executeTransactionWithin(QueryDsl.scala:95)
at org.squeryl.dsl.QueryDsl$class.transaction(QueryDsl.scala:64)
at org.squeryl.PrimitiveTypeMode$.transaction(PrimitiveTypeMode.scala:40)
at generator.Generator$$anonfun$generatePlanets$2.apply(Generator.scala:330)
at generator.Generator$$anonfun$generatePlanets$2.apply(Generator.scala:55)
at generator.Generator$.generatePlanets(Generator.scala:55)
at generator.Generator$.generateGalaxy(Generator.scala:36)
at controllers.MainRouter$.generateGalaxy(MainRouter.scala:29)
at play.mvc.ActionInvoker.invokeWithContinuation(ActionInvoker.java:543)
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:499)
at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:493)
at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:470)
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:158)
... 1 more
Caused by: java.lang.NullPointerException
... 14 more
scalatra を Web フレームワークとして使用すると問題なく動作したため、クエリに問題がないことはわかっています。すべてを1 つのトランザクション ブロックに入れることもできますが、それはあまりエレガントではありません。また、この場合に機能するかどうかもわかりません。planetList
リストには約 300 万のメンバーが含まれているため、データベースを分割する前に scala がメモリ不足になりました。 50k 要素の小さなブロックに挿入します。