2012-08-03 77 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