异步事务导致IllegalStateException

时间:2014-03-04 10:46:27

标签: scala playframework-2.0 slick mariadb hikaricp

我目前有一个问题需要处理。 我试图异步管理一个slick2.0事务。原因是与我合作的未来。

我编写了自己的方法来与光滑异步处理会话:

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
  }
}

我像这样使用它(注入了dataSource):

withAsyncTransaction { implicit session =>
 ... CRUD
}

stacktrace:

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

偶尔会发生错误,并且它不依赖于连接池。与boneCP相同的问题。有人有想法吗?

将非常感谢帮助。 OliverKK

1 个答案:

答案 0 :(得分:2)

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

请参阅withTransaction的实施:https://github.com/slick/slick/blob/06ee4edade81633db10724a858f427deb563edfc/src/main/scala/scala/slick/jdbc/JdbcBackend.scala#L476

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