Play 2.4 中的 Slick 3.0 交易

Slick 3.0 transactions in Play 2.4

我有一个控制器,它对数据库模型 类 进行各种调用,在 PostgreSQL 数据库上执行各种操作。我想在单个事务中执行所有这些操作。在 Play 2.3 中,我能够将代码包装在 DB.withTransaction { ... } 中以使其在单个事务中执行所有操作。

对于 Play 2.4 和 Slick 3.0,Slick 似乎处理连接管理,DB.withTransaction 似乎不再是处理此问题的正确方法(它抛出 IllegalArgumentException 消息 "Could not find database for default"反正)。从控制器内部对事务内的 Slick 操作进行分组的正确方法是什么?

你的问题的解决方案是DBIO composition

首先,你所有的原子操作都应该由一个DBIOAction实现(一个DBIOAction代表一个将在数据库上执行的操作)。

接下来,您可以将所有 DBIOAction 组合在一起,使用 andThenflatMap,或使用 for comprehension(参见 DBIOAction api)

当您拥有组合的 DBIO 时,您可以调用 .transactionally 使 DBIOAction 在 db 上执行时具有事务性。

样本:

def updateUsername(id: Long, username: String) = Schemas.users.filter(_.id === id).map(_.username).update(username)
def updateUserAddress(id: Long, address: String) = Schemas.addresses.filter(_.id === id).map(_.address).update(address)
def getUser(id: Long) = Schemas.users.filter(_.id === id).head

val operations = for {
   _ <- updateUserName(1, "foo")
   _ <- updateUserAddress(1, "bar")
   user <- getUser(1)
} yield user

db.run(operations.transactionally)

获取db对象的方法在Play文档中有说明。