【问题标题】:Asynchronous transaction causes IllegalStateException异步事务导致 IllegalStateException
【发布时间】:2014-03-04 10:46:26
【问题描述】:

我目前必须处理一个问题。 我正在尝试异步管理 slick2.0 事务。原因是我使用的期货。

我编写了自己的方法来使用 slick 异步处理会话:

def withAsyncTransaction[T](implicit block: Session => Future[T]): Future[T] = {
  val session = Database.forDataSource(dataSource).createSession()
  session.conn.setAutoCommit(false)
  block(session).recover {
    case e: Exception =>
      session.conn.rollback()
      session.conn.close()
      throw e
  }.map { v =>
    session.conn.commit()
    session.conn.close()
    v
  }
}

我是这样使用的(数据源被注入):

withAsyncTransaction { implicit session =>
 ... CRUD
}

堆栈跟踪:

The datasource has been shutdown.
java.lang.IllegalStateException: The datasource has been shutdown.
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:62)

错误是偶尔发生的,它不依赖于连接池。 boneCP 也有同样的问题。有人有想法吗?

我们将不胜感激。 奥利弗KK

【问题讨论】:

  • 这很奇怪。我对 Slick 不熟悉,但似乎偶尔会在 DataSource 本身而不是连接上调用 close(),这可能吗?
  • 在阅读了 Slick 之后,似乎使用带有会话的 Futures 是危险的,所以我不确定你想要做什么是可能的。请参阅文档here,搜索单词“escapes”以获取警告。我建议在 Slick 论坛上提问。

标签: scala playframework-2.0 slick mariadb hikaricp


【解决方案1】:

我不确定究竟是什么导致了您所看到的错误,但我刚刚从经验中了解到,将期货、浮油和交易结合起来会让人头疼。您编写的代码似乎应该可以工作,只是 slick 的某些部分假定自动提交设置没有在其背后更改。

查看withTransaction的实现:https://github.com/slick/slick/blob/06ee4edade81633db10724a858f427deb563edfc/src/main/scala/scala/slick/jdbc/JdbcBackend.scala#L476

它假定它的私有变量inTransaction 是最新的,并且如果它认为它还没有在事务中,它将在操作结束时将 autocommit 设置为 true。这意味着您使用已创建的会话编写的任何调用withTransaction 的代码都将提交事务并将自动提交重置为真。现在,只要您不调用withTransaction,这似乎没问题,但是当您可能没想到时,有一些巧妙的操作会在内部调用它。例如,如果您使用++= 执行批量插入,它将调用withTransaction 并最终提交您创建的事务,之后您执行的每条语句都将自动提交。

【讨论】:

    猜你喜欢
    • 2010-10-02
    • 2014-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-15
    • 2018-09-28
    • 2015-04-20
    • 2012-05-09
    相关资源
    最近更新 更多