【问题标题】:Using Slick 3.0 transactions while migrating from Squeryl从 Squeryl 迁移时使用 Slick 3.0 事务
【发布时间】:2020-03-02 15:26:45
【问题描述】:

我正在将一些 Scala 代码从 Squeryl 迁移到 Slick。一切都很顺利,直到我碰到交易的话题。 Squeryl 使处理事务变得非常简单:您只需将代码(无论是否与 DB 相关)包装在 transaction 块中即可。

从我可以在网上收集的示例来看,似乎有人希望重新构建整个项目,使其能够很好地使用它的一元方法和理解,这是我真正想避免的事情。

考虑一段任意代码,例如:

def f(): Unit = {
    UserRepository.getUser()
    ... some imperative code
    ServiceRepository.getServer()
    ...
    ServerRepository.updateServer(...)
    ...
    UserRepository.insertNewUser(...)
}

有没有一种方法可以轻松地将其包装在某种事务块中,而无需更改方法的内部逻辑?

【问题讨论】:

  • 我相信如果您使用.transactionally,您将无法在调用之间压缩其他代码。不确定是否有其他选项可以强制执行数据库事务

标签: scala slick


【解决方案1】:

有没有一种方法可以轻松地将其包装在某种事务块中,而无需更改方法的内部逻辑?

简短的回答是否定的,但这取决于对UserRepository 和其他方法的调用返回什么:

  • 如果它们是 Future[T](或者如果您已阻止从未来获取值),则您已经运行了查询,所以它是一个否,因为您在 Slick 层之外。

  • 如果它们是动作 (DBIO) 甚至是查询,那么它可能不会改变内部逻辑:您必须将动作组合在一起,但可以通过混合任意代码来实现。例如,flatMap(或用于理解)将允许这样做。

作为混合逻辑和组合动作的示例,您可以编写如下代码:

val action = for {
  user <- UserRepository.getUser // a DBIO[User]
  result <- if user.notPermitted() {
      DBIO.failed(new IOException("Not allowed")
  } else {
      DBIO.successful(user)
  }  
} yield result

介绍适用于DBIO 的方法和值(可能使用successfulfailed)可能会使这种转换对您来说不那么痛苦。有一个答案可能会为混合逻辑和动作提供更多想法:https://stackoverflow.com/a/31490020/154248

您必须执行.transcationally 中的最终组合操作,以确保它们的所有操作都在事务中运行。描述在:https://scala-slick.org/doc/3.3.2/dbio.html#transactions

我想到了另外两种可能性:

  • 可以想象,您可以在 Slick 中实现自己的后端。但这似乎是一项艰巨的工作,而且您将一直与 Slick 其余部分的想法作斗争。

  • 1234563 3 作为一个单独的工作线。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-23
    • 1970-01-01
    相关资源
    最近更新 更多