这是一个常见的错误 - 转换为Future
到早(换句话说,调用db.run(...)
到早)。
你需要做的是删除这个方法,因为它(可能有点不直观)带来的弊大于利:
implicit def run[A](action: DBIOAction[A, NoStream, _ <: slick.dbio.Effect]): Future[A] = {
db.run(action)
}
经验法则基本上是,您通常希望严格控制实际的数据库交互(和事务边界),因此我建议不要进行任何类型的操作implicit
就在这个区域。毕竟这是这个库背后的驱动理念之一 -Slick
尝试在应用程序和数据库之间的交互中非常明确(与经典的 ORM 相反 - 使用访问器可能实际上触发了对数据库的延迟调用,或者通过 mutator 设置值可能会导致实际的数据库更新)。
然后你需要将返回类型更改为此(更改为Future
to 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
to Future
您失去了将操作捆绑到单个事务中的能力。因此,您基本上可以使用 DBIO 的不同转换来完成所有操作(通常的东西:map
, flatMap
, seq
等等)并且只有在最后一步你才开火db.run(yourComposedDbio.transactionally)
.
编辑:
以下是有关处理交易的更多信息和DBIO
几周前我做的演讲的作文。相关幻灯片:http://slides.com/pdolega/slick-101#/85(并进一步)。
另外,Dave Gurnell 举办了一个很棒的研讨会,他在 01:05:00 左右讨论了这个问题(链接在这里:https://vimeo.com/148074461 )