我有一个控制器,它对在PostgreSQL数据库上执行各种操作的数据库模型类进行各种调用。我想在单个事务中执行所有这些操作。在Play 2.3中,我能够将代码包装在DB.withTransaction { ... }
中,以使其在单个事务中执行所有操作。
使用Play 2.4和Slick 3.0,似乎Slick处理连接管理,并且DB.withTransaction
似乎不再是处理此问题的正确方法(它会向IllegalArgumentException
抛出消息“无法找到默认数据库“无论如何)。在控制器内对事务中的Slick操作进行分组的正确方法是什么?
答案 0 :(得分:2)
您的问题的解决方案是DBIO composition。
首先,所有原子操作都应该由DBIOAction
实现(A DBIOAction
表示将在DB上执行的操作。)
接下来,您可以使用andThen
,flatMap
或使用for comprehension
(请参阅DBIOAction api)将所有DBIOAction组合在一起
当你拥有编写的DBIO时,你可以调用.transactionally
来在DB上执行DBIOAction事务。
样品:
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)
Play文档中解释了获取db
对象的方法。