1

作成した DAO レイヤーに行き詰まりました。単一のケースでは問題なく動作しますが、トランザクション ブロックで複数の Bean インスタンスを永続化する必要がある場合、自分自身をコーナーにコーディングしていることに気付きます。なんで?以下の DAO create メソッドを確認してください。

def create(e: Entity): Option[Int] =
  db.handle withSession { implicit ss: Session=>
    catching( mapper.insert(e) ) option match {
      case Some(success) => Some(Query(sequenceID))
      case None => None
    }
  }

セッション ブロック内で発生するクエリは自動コミットに設定されているため、複数の永続化操作をトランザクション ブロックにラップすることはできません。たとえば、これは、新しいメンバーのサブスクリプションを処理する理解のために簡略化されたものです。

val result = for{
  u <- user.dao.create(ubean)
  m <- member.dao.create(mbean)
  o <- order.dao.create(obean)
} yield (u,m,o)
result match {
  case Some((a,b,c)) => // all good
  case _ => // failed, need to rollback here
}

手動でクエリを実行することもできますが、それは醜い速さになります

db.handle withSession { implicit ss: Session=>
  ss.withTransaction {
    val result = for{
      u <- safe( UserMapper.insert(ubean) )
      ...
    }
    def safe(q: Query[_]) = 
      catching( q ) option match {
        case Some(success) => Some(Query(sequenceID))
        case None => None
      }
  }
}

DAOレイヤーにカプセル化するのではなく、アプリケーション全体でデータベース、セッションなどを提供する必要があるため、エラー処理を複製することになります

この問題を回避する方法について、ここで賢明なアドバイスを持っている人はいますか? 私は理解のための簡潔さが本当に好きです、Scalaは岩です;-)、アイデアは大歓迎です!

4

1 に答える 1

0

OK、誰かがより良いアイデアを持っていない限り、ここに私が取り組んでいるものがあります:

DAO からエンティティへの関係は 1 対 1 の関係であり、ScalaQuery はセッション ブロックで実行されたクエリを自動コミットするため、私の DAO 実装では個別のエンティティに対して複数の挿入を実行することはできません。

回避策は、特定のエンティティに関連付けられていない GenericDAO を作成することです。これは、トランザクション クエリ機能を提供し、エラー処理を親トレイトに抽出します。

    def createMember(...): Boolean = {
      db.handle withSession { implicit ss: Session=>
        ss.withTransaction {
          val result = for{
            u <- safeInsert( UserMapper.insert(ubean) )(ss)
            ...
          }
          ...

コントローラー層では、実装dao.createMember(...)は非常に素晴らしく、いも、安全に理解できるクールなものを使用したトランザクション挿入になります。

于 2012-05-31T18:45:07.510 に答える