如何在 slick 中使用事务

How to use transaction in slick

我有这样的插入方法(权重是索引)

implicit def run[A](action: DBIOAction[A, NoStream, _ <: slick.dbio.Effect]): Future[A] = {
    db.run(action)
  }

def insert(newCategory: CategoryExtractor): Future[Either[String, CategoryResponse]] = {
        category.map(_.weight).max.result.flatMap {
          case Some(weight) =>
            val temp = newCategory.copy(weight = weight+1)
            (category += temp).andThen(DBIO.successful(Right(toCategoryExtractor(temp))))
          case None =>
            val temp = newCategory.copy(weight = 1)
            (category += temp).andThen(DBIO.successful(Right(toCategoryExtractor(temp))))
        }
  }

我叫了 2 次

insert(CategoryExtractor("1", "name", "scala every where", 0, 0, 0, None)) onComplete {
    case Success(data) => println(data)
  }

insert(CategoryExtractor("2", "name", "haskell every where", 0, 0, 0, None)) onComplete {
    case Success(data) => println(data)
  }

它return异常(唯一索引)。

如何解决这个问题,我不使用 for-comprehension 或在第一个 onComplete 中插入。只需调用它 2 次。

谢谢。

这是一个常见的错误 - 提前转换为 Future(换句话说,提前调用 db.run(...))。

您需要做的是删除此方法,因为它(可能有点不直观)弊大于利:

implicit def run[A](action: DBIOAction[A, NoStream, _ <: slick.dbio.Effect]): Future[A] = {
    db.run(action)
  }

经验法则基本上是您通常希望严格控制实际的数据库交互(和事务边界),因此我建议不要在这方面使用任何类型的 implicit。毕竟它是这个库背后的驱动思想之一 - Slick 试图在应用程序和数据库之间的交互中非常明确(与经典 ORM 相反 - 使用访问器可能实际上触发了对数据库的延迟调用或设置一个值通过 mutator 可能会导致实际的数据库更新。

那你需要把return类型改成这样(把Future改成DBIO):

def insert(newCategory: CategoryExtractor): DBIO[Either[String, CategoryResponse]] = {
...
  }

然后你这样做:

val firstInsert = insert(CategoryExtractor("1", "name", "scala every where", 0, 0, 0, None)) map {
    data => println(data)
}

val secondInsert = insert(CategoryExtractor("2", "name", "haskell every where", 0, 0, 0, None)) map {
    data => println(data)
}

db.run(DBIO.seq(firstInsert, secondInsert).transactionally))

基本上事情是:一旦你将 DBIO 转换为 Future 你就失去了将动作捆绑到单个事务中的能力。 所以你基本上做一切都使用不同的 DBIO 转换(通常的东西:mapflatMapseq 等)并且仅在最后一步触发 db.run(yourComposedDbio.transactionally).

编辑: 这里有一些关于处理交易和 DBIO 组合的更多信息,来自我几周前的演示文稿。相关幻灯片:http://slides.com/pdolega/slick-101#/85(以及更多)。

Dave Gurnell 也有一个很棒的研讨会 运行,他在附近谈到了这个:01:05:00(link 这里:https://vimeo.com/148074461