Slick 3 Transactions

Bom*_*gar 15 scala slick

我对这个光滑的3文档描述交易的方式感到困惑.我有两个看起来像这样的代码:

def doSomething(???) = DB.withTransaction { implicit session => 
    userDao.doSomething(???)
    addressDao.doSomething(???)
    contactDao.doSomething(???)
}
Run Code Online (Sandbox Code Playgroud)

如何在光滑3中跨越交易?

Gre*_*man 17

请查看http://slick.typesafe.com/doc/3.0.0/dbio.html#transactions-and-pinned-sessions中的文档.

我们的想法是将一系列IO操作包装成transactionally如下例所示:

val a = (for {
   ns <- coffees.filter(_.name.startsWith("ESPRESSO")).map(_.name).result
   _ <- DBIO.seq(ns.map(n => coffees.filter(_.name === n).delete): _*)
} yield ()).transactionally

val f: Future[Unit] = db.run(a)
Run Code Online (Sandbox Code Playgroud)

这样Slick仍然可以反应性地处理所有操作,但它会在一个事务中按顺序运行它们.

所以你的例子看起来像这样:

def doSomething(???) = (for {
  _ <- userDao.doSomething(???)
  _ <- addressDao.doSomething(???)
  _ <- contactDao.doSomething(???)
} yield()).transactionally
Run Code Online (Sandbox Code Playgroud)

  • 很遗憾,我必须在抽象级别上处理动作连接. (7认同)
  • 我发现函数范围是一种自然直观的事务范围.这个新的基于Action的API是复杂的,不可读的和不自然的,我认为他们对那些糟糕的设计决策感到退步. (7认同)
  • db.run部分让我烦恼.返回值也不是"正常"期货. (3认同)
  • @GregorRayman好的,这就是我的想法.然后我的下一个问题是:在光滑3中设计dao的"最佳"方法是什么?是否所有dao函数都返回DBIOAction,当你需要dao函数的实际结果时,你运行db.run(someDao.someFunction())? (3认同)
  • 另外我必须在那个抽象层上"运行"它很烦人 (2认同)
  • 当您需要获得中间结果并保留在事务内时,这似乎有问题。例如,如果您在事务内部有一个if语句。 (2认同)
  • 一种常见的情况是,将这些链接的操作中的一个作为插入操作,随后的操作将其更新的内容更新为在其表中包括插入主键作为外键。在执行另一个ID并仍然保持所有事务性之前,如何从一个ID中提取新生成的ID的值? (2认同)

pan*_*her 14

val dbAction = (
  for {
    user <- userTable.doSomething
    address <- addressTable.doSomething
    contact <- contactTable.doSomething
  } yield()
).transactionally

val resultFuture = db run dbAction
Run Code Online (Sandbox Code Playgroud)

您只需要将您的操作包装成"事务性".Slick将负责将所有包装的数据库操作作为事务运行.

除了具有更加反应/功能/异步编写代码的方式的标准优势之外,它还允许几个性能改进.就像它可以在运行时确定多个动作是否可以使用相同的会话.在Slick 2.0中,每当你使用'withTransaction'或'withSession'打开一个新的jdbc会话时,它就有可能重用它.