我最近从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)
}
}
}
现在,如果某人对交易不感兴趣,他们只需调用insert()
方法即可。
如果我们需要进行一些交易,可以使用insertWithTransaction()
块中的db.withTransaction
来完成。
例如:
db.withTransaction { implicit session =>
insertWithTransaction(row1)
insertWithTransaction(row2)
//check some condition, invoke session.rollback if something goes wrong
}
但是使用slick-3,事务上只能应用于查询。 这意味着,无论我们需要在插入后集中执行某些逻辑,都有可能。如果他们使用事务,每个开发人员都需要显式地手动处理这些场景。我相信这可能会导致错误。我试图在插入操作中抽象整个逻辑,以便实现者只需要担心事务成功/失败
还有其他方法,在slick-3中,我可以将同一个会话传递给多个方法,以便一切都可以在单个数据库会话中完成。
答案 0 :(得分:1)
您遗失了一些内容:O(N)
并不适用于.transactionally
,而是适用于Query
。
然后,DBIOAction
可以通过使用monadic组合由多个查询组成。
以下是来自文档的例子:
DBIOAction
val action = (for {
ns <- coffees.filter(_.name.startsWith("ESPRESSO")).map(_.name).result
_ <- DBIO.seq(ns.map(n => coffees.filter(_.name === n).delete): _*)
} yield ()).transactionally
由action
查询和与第一个查询返回的行一样多select
个查询组成。所有创建在事务中执行的delete
。
然后,要对数据库运行操作,您必须调用DBIOAction
,所以,像这样:
db.run
现在,回到你的例子,让我们说你想在插入后应用val f: Future[Unit] = db.run(action)
查询,你可以用这种方式创建一个动作
update
希望它有所帮助。