我想实现实用程序函数/ 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规范方式来实现这个? 感谢。
答案 0 :(得分:3)
方法tx
接受1参数的函数作为参数,方法saveMyEntity
不接受任何参数,因此不能将其用作A => B
(1参数的函数)。
您没有单独使用a
和f
,因此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