Yad*_*nan 7 scala transactions slick
我最近从Slick-2切换到Slick-3.一切都与光滑-3一起工作得非常好.但是,在交易方面我遇到了一些问题.我已经看到了不同的问题和示例代码,其中transactionally
和withPinnedSession
用于处理事务.但我的情况略有不同.transcationally和withPinnedSession都可以应用Query
.但我想要做的是将同一个会话传递给另一个方法,该方法将执行一些操作并希望在同一个事务中包装多个方法.
我有下面的slick-2代码,我不知道如何用Slick-3实现这个.
def insertWithTransaction(row: TTable#TableElementType)(implicit session: Session) = {
val entity = (query returning query.map(obj => obj) += row).asInstanceOf[TEntity]
// do some operations after insert
//eg: invoke another method for sending the notification
entity
}
override def insert(row: TTable#TableElementType) = {
db.withSession {
implicit session => {
insertWithTransaction(row)
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在,如果某人对交易不感兴趣,他们就可以调用该insert()
方法.如果我们需要做一些事务,可以通过insertWithTransaction()
在db.withTransaction
块中使用来完成.
例如:
db.withTransaction { implicit session =>
insertWithTransaction(row1)
insertWithTransaction(row2)
//check some condition, invoke session.rollback if something goes wrong
}
Run Code Online (Sandbox Code Playgroud)
但是使用slick-3,事务上只能应用于查询.这意味着,无论我们需要在插入后集中执行某些逻辑,都有可能.如果他们使用事务,每个开发人员都需要显式地手动处理这些场景.我相信这可能会导致错误.我试图在插入操作中抽象整个逻辑,以便实现者只需要担心事务成功/失败
还有其他方法,在slick-3中,我可以将同一个会话传递给多个方法,以便一切都可以在单个数据库会话中完成.
您错过了一些东西:.transactionally
不适用于 a Query
,但适用于 a DBIOAction
。然后,aDBIOAction
可以通过使用单子组合来由多个查询组成。
这是来自文档的示例:
val action = (for {
ns <- coffees.filter(_.name.startsWith("ESPRESSO")).map(_.name).result
_ <- DBIO.seq(ns.map(n => coffees.filter(_.name === n).delete): _*)
} yield ()).transactionally
Run Code Online (Sandbox Code Playgroud)
action
select
由一个查询和delete
与第一个查询返回的行数相同的查询组成。所有创建的内容DBIOAction
都在事务中执行。
然后,要对数据库运行操作,您必须调用db.run
,因此,如下所示:
val f: Future[Unit] = db.run(action)
Run Code Online (Sandbox Code Playgroud)
现在,回到您的示例,假设您想update
在插入后应用查询,您可以通过这种方式创建一个操作
val action = (for {
entity <- (query returning query.map(obj => obj) += row)
_ <- query.map(_.foo).update(newFoo)
} yield entity).transactionally
Run Code Online (Sandbox Code Playgroud)
希望能帮助到你。