在Scala中实现事务方面

时间:2013-07-08 06:43:42

标签: scala

我想实现实用程序函数/ monad / aspect来管理scala中的hibernate事务,并寻找有关最佳方法的建议。

首先,我尝试创建如下的currying函数:

def session() = sessionFactory.getCurrentSession()

def transaction() = session().getTransaction()

def tx[A, B](f: A => B)(a: A): B = {
try {
  session().beginTransaction()
  val r = f(a)
  transaction().commit()
  return r
} catch {
  case e: 
    Throwable => 
      transaction().rollback()
      throw e
} finally {
  session.close()      
}

}

我的想法是我可以使用此功能:

def saveMyEntity() {
  session().save(new MyEntity)
}

tx(saveMyEntity)()

并且saveMyEntity调用将被包装到事务中。

不幸的是,我在此代码中遇到以下错误:

[error]  found   : () => Unit
[error]  required: ? => ?
[error]   tx(saveMyEntity)()

我仍在学习scala,并寻求改进方法的建议。也许我可以某种方式修改我的功能以获得更好的结果?或者添加另一个单元类型特定功能?或者选择其他路径?

有什么想法吗? 任何scala规范方式来实现这个? 感谢。

2 个答案:

答案 0 :(得分:3)

方法tx接受1参数的函数作为参数,方法saveMyEntity不接受任何参数,因此不能将其用作A => B(1参数的函数)。

您没有单独使用af,因此a无需使用def tx[B](f: => B): B = { 。您可以在此处使用by-name参数:

saveMyEntity

如果您想将Unit => Unit用作tx[Unit, Unit](_ => saveMyEntity)(()) ,则应明确创建函数:

import util.control.Exception.allCatch

def withSession[T](f: Session => T):T = {
  val session = ??? // start session here
  allCatch.anfFinally{
    session.close()
  } apply { f(session) }
}

def inTransaction[T](f: => T): T =
  withSession{ session =>
    session().beginTransaction()
    try {
      val r = f(a)
      transaction().commit()
      r
    } catch {
      case e: Throwable => 
        transaction().rollback()
        throw e
    }
  }

inTransaction{saveMyEntity}

我猜某些更改可能会提高您的代码可读性:

{{1}}

答案 1 :(得分:0)

object TestTransaction
{
  def executeInTransaction(f: => Unit)={
    println("begin")
    f
    println("end")
  }
  executeInTransaction {
    println("action!")
  }
}

产生

  begin
  action!
  end