2015-05-21 53 views
10

我最近從Slick-2切換到了Slick-3。 slick-3的一切都很好。但是,在交易方面,我遇到了一些問題。 我看到了不同的問題和示例代碼,其中transactionallywithPinnedSession用於處理事務。但我的情況稍有不同。 transcationally和withPinnedSession都可以應用於Query。但我想要做的是將同一個會話傳遞給另一個方法,該方法將執行一些操作,並且想要在同一個事務中包裝多個方法。在Slick 3中的多個方法之間共享數據庫會話

我有下面的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()方法。 如果我們需要做一些交易,可以在db.withTransaction區塊中使用insertWithTransaction()來完成。

對於例如:

db.withTransaction { implicit session => 
    insertWithTransaction(row1) 
    insertWithTransaction(row2) 
    //check some condition, invoke session.rollback if something goes wrong 
} 

但隨着光滑-3,事務可以僅查詢應用。這意味着,無論我們需要在插入後集中執行某些邏輯,都有可能。每個開發人員都需要手動處理這些場景,如果他們正在使用事務。我相信這可能會導致錯誤。我試圖在插入操作中抽象整個邏輯,以便實現者只需要擔心事務成功或失敗

在slick-3中有沒有其他方法可以將同一會話傳遞給多個方法,以便一切都可以在單個數據庫會話中完成。

回答

1

您錯過了某些東西:.transactionnaly不適用於Query,但適用於DBIOAction。 然後,一個DBIOAction可以通過使用monadic組成組成的多個查詢。

下面是一個來自爲例文檔來:

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

actionselect查詢和多達delete查詢作爲第一個查詢返回的行。所有這些都會創建在事務中執行的DBIOAction

然後,要對數據庫運行的動作,你必須調用db.run,所以,像這樣:

val f: Future[Unit] = db.run(action) 

現在,回過頭來你爲例,假設你想申請一個update查詢在你插入之後,你可以用這種方式創建一個動作

val action = (for { 
    entity <- (query returning query.map(obj => obj) += row) 
    _ <- query.map(_.foo).update(newFoo) 
} yield entity).transactionnaly 

希望它有幫助。

相關問題