Squeryl和Play!框架在Scala中存在问题。

4

使用Squeryl和Play!时遇到了一个奇怪的问题。

正常情况下,一切都完全正常。但是,如果在同一次请求中使用多个事务,就会出现错误。

这是我设置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框架时,它们运行良好。我可以将所有内容放入一个事务块中,但那并不真正优雅,而且我也不确定在这种情况下是否会起作用 - planetList 列表有大约三百万成员,这使得Scala在将数据库插入分成50k个元素的较小块之前耗尽了内存。


你有没有得到答案?我也遇到了同样的问题。 - Ladlestein
如果我没记错的话,我只采用了一个事务。 - Mononofu
我也遇到了很多类似的问题,尽管我的问题有点不同且更简单。当我通过RenderArgs传递一个Squeryl值时,它似乎保存了整个SQL查询并尝试再次运行它...而不仅仅是传递该值。如果您找到了更简单的解决方法,请告诉我。 - crockpotveggies
2个回答

1
我想看看第一个交易是如何相关的,它是否会在之前立即执行?它们是嵌套的吗?
当你有两个交易时,你可以这样做:
val s1 = Session.create( DB.getConnection, new MySQLAdapter) )
val s2 = Session.create( DB.getConnection, new MySQLAdapter) )


using(s1) {...   .... s1.connection.commit}
using(s2) {...   .... s1.connection.commit}

交易是按顺序执行的:进行一些处理,然后提交到数据库,再进行一些处理,写入到数据库等等。我本以为每个请求只能使用一个会话。 - Mononofu

1
你能否把你的问题重新发布到Squeryl邮件列表中?我不熟悉Play!,但是我知道其他用户和提交者可能会了解。如果您可以在GitHub上发布一个示例项目并包含链接,那将非常有帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接