2012-08-03 75 views
0

以一個數據庫事務:階隱式標識

def create(model: Model, orderNum: String) = { 
    db.handle withSession { implicit ss: Session=> 
    ss.withTransaction { // auto commit now set to false 
     val result = for { 
     uid <- repo.user.create(model) 
     mid <- repo.membership.create(uid) 
     oid <- repo.orders.create(model, uid, orderNum) 
     } yield uid 
     result fold( 
     e=> { ss.rollback; Left(e) }, 
     s=> { Cache.remove("member.directory"); Right(s) } 
    ) 
    } 
    } 
} 

如果庫用戶創建的實現需要一個隱含的會議,是相同會議的withTransaction啓用會議上面,或者是隱含價值「是一個「而不是」身份?「

def create[T <: User](t: T)(implicit ss: Session) = // what Session is this? 
    for { 
    uid <- either(Users.insert(Users(t)), i18n("user not created")) 
    ur <- either(UserRoles.insert(UserRole(uid, t.role)), i18n("user role not created")) 
    } yield uid 

我能通過在會議明確repo.user.create(model)(ss)和具有創造採取明確的會議,但我想知道是否更簡潔/便利隱含的方式提供了相同的結果,交易啓用會話。

回答

0

不知道下面是什麼你正在嘗試做一個忠實的抽象,但我希望它能幫助:

class Store(var x: Int) { 
    def flip() { x = -x } 
} 

object M1 { 
    implicit val store2 = new Store(2) 

    def create(s: String) = { 
    implicit val store3 = new Store(3) 

    { implicit store: Store => 
     println("[M1.create] store.x = " + store.x) 
     store.flip() 
     M2.create("tummy") 
     println("[M1.create] store.x = " + store.x) 
    } 
    } 
} 

object M2 { 
    implicit val store4 = new Store(4) 

    def create(s: String)(implicit store: Store) = { 
    println("[M2.create] store.x = " + store.x) 
    store.flip() 
    } 
} 

M1.create("dummy")(new Store(1)) 

輸出是:

[M1.create] store.x = 1 
[M2.create] store.x = -1 
[M1.create] store.x = 1 
  • new Store(1)明確轉交給M1.create轉發給M2.create

  • 編譯器明顯忽略了其他隱式存儲庫store2, store3, store4

1

如果我正確地理解了你,你正在使用ScalaQuery,並且你想讓你的方法也在用戶從外部提供會話時工作。

DEF withSession [T](F:⇒T):T運行所提供的thunk用一個新的會話和 在結束時自動關閉會話。

def withSession [T](f: (Session)⇒T):T用新會話運行提供的功能,並在最後自動關閉會話。

這些都正在創造一個新的事務,所以我會去的方式是使用一個可選[會議]作爲隱含的而且默認爲無

def onProvidedOrCreatedSession[K](f: Session => K)(session:Option[Session]) = { 
    session match { 
     case Some(s) => f(s) 
     case None => db.withSession { f } 
    } 
    } 

    def create(model: Model, orderNum: String)(implicit session:Option[Session]=None){ 
    onProvidedOrCreatedSession( 
     implicit s => s.withTransaction { val x = 10 } 
    )(session) 

    } 
+0

+1,有趣。如您所見,正在嘗試通過將會話隱式傳遞到外部查詢方法來在本地事務塊之外運行查詢。通過明確地傳遞會話(我在我的「真實」代碼中實際做的),我的印象是ScalaQuery將使用顯式傳遞的會話(應該將自動提交設置爲false)。我確實通過顯式會話傳遞運行了一些測試,並且在本地事務塊中的任何一點失敗都會回滾所有執行的查詢 – virtualeyes 2012-08-03 15:46:04

+1

再次看SQ源,您是正確的;但是,我沒有在外部查詢方法中使用withSession或withTransaction;他們收到已經存在的啓用事務的會話,這就是爲什麼當失敗時,本地事務塊會回滾所有外部執行的查詢 – virtualeyes 2012-08-03 15:53:02

+0

這是正確的。如果您在單個事務內朗讀多個查詢並且一個失敗,則所有查詢都會回滾。這是Acid – Edmondo1984 2012-08-03 17:37:27