2013-07-08 5 views
3

나는 스칼라에서 최대 절전 모드 트랜잭션을 관리하고 최상의 접근 방법에 대한 조언을 구하기 위해 유틸리티 함수/모나드/애스펙트를 구현하고자한다.스칼라에서 트랜잭션 aspect 구현하기

는 우선 다음과 같은 무두질 기능을 만들려고 :

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)() 

나는 여전히 스칼라 학습, 나의 접근 방식을 개선하기 위해 조언을 찾고. 어쩌면 더 나은 결과를 얻기 위해 어떻게 든 함수를 수정할 수 있습니까? 또는 다른 Unit type 특정 기능을 추가합니까? 아니면 다른 경로를 선택 하시겠습니까?

아이디어가 있으십니까? 이것을 구현하는 스칼라 표준 방법은 무엇입니까? 감사합니다. .

답변

3

메서드 tx은 매개 변수와 메서드로 1 개의 인수를 허용합니다. saveMyEntity은 인수를 허용하지 않으므로 A => B (1 인수의 기능)으로 사용할 수 없습니다.

af을 별도로 사용하지 않으므로 a은 필요하지 않습니다. 명시 적으로 작성해야 saveMyEntityUnit => Unit로 기능을 사용하려면

def tx[B](f: => B): B = { 

:

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} 
:

tx[Unit, Unit](_ => saveMyEntity)(()) 

나는 몇 가지 변경 사항이 코드의 가독성을 향상시킬 수 있습니다 추측 여기 by-name 매개 변수를 사용할 수 있습니다

+0

@ crypto5 : '단위'는 스칼라의 일반 유형입니다. 메소드를'saveMyEntity (u : Unit)'로 정의 할 수 있습니다. 그것은 쓸모 없지만 편집을 수정합니다. – senia

+0

좋습니다.이 방법은 가장 깨끗해 보입니다. 감사합니다. – crypto5

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

:

begin 
    action! 
    end