2011-12-15 10 views
2

JPAを既に使用しているJPA EnitytManager(およびトランザクション)のアプリケーションは、現在のところリファクタリング中です。現在、DAOレイヤーにスコープされています。リポジトリ層とサービス層もあります。私は、サービスレイヤをトランザクションにし、サービスレイヤ上で要求ごとに単一のEntityMangerを持っています。理想的には、私のサービス層またはリポジトリ層にJPAに関する情報を知りたくはありません。JPAモデルの検証とトランザクション処理

現在、リポジトリとサービスレイヤは、DAOレイヤから取得した独立したエンティティで動作します。モデルに変更が加えられ、エンティティはDAOレイヤにマージされます。新しい構造では、エンティティは要求全体の中で管理されたままであり、1つの要求は1つのトランザクション内に含まれます。変更はトランザクションの終了時に自動的にコミットされます。これはJPAの精神ではるかに多く、最も一般的なケースではうまく機能します。

場合によってはモデルに変更が加えられ、モデルが検証されます。モデルがもはや有効でない場合、変更は保存されません。

この例では、プロセスは基本的にグラフであり、グラフ全体が検証され、自己参照はなく、すべてのノードに到達可能でなければならず、最初のノードにはいくつかの特別な要件があります。最終的なノードなどとなります。まず、モデルの変更を行い、次にモデルを検証します。古い

リポジトリ層コード:私が考える新しい構造では

changeProcessModel(); 
messages = ProcessValidator.validate(process); 
if (messages.hasNoErrors()) { 
    processDao.merge(process); 
    messages.addInfoMessage("Process was updated succesfully"); 
} 
return messages; 

は、私は3つのオプションを持っていると私は、ベストプラクティスと考えられている1質問だ、または任意の他の選択肢があるかどうか。

新しいコードオプション1:

changeProcessModel(); 
messages = ProcessValidator.validate(process); 
if (messages.hasNoErrors()) { 
    messages.addInfoMessage("Process was updated succesfully"); 
} else { 
    throw new InvalidProcessException(messages); 
} 
return messages; 

虐待のこのコードの並べ替え、いくつかのビジネスルールの検証のためRuntimeException。これはベストプラクティスとはみなされませんが、トランザクションはロールバックされます。これは、例えばエンティティが検証しない場合にも例外をスローするBean Validationと互換性があるようです。

新しいコードオプション2:

changeProcessModel(); 
messages = ProcessValidator.validate(process); 
if (messages.hasNoErrors()) { 
    messages.addInfoMessage("Process was updated succesfully"); 
} else { 
    em.getTransactionManager.rollback(); 
} 
return messages; 

このコードは、JPA TransactionManagerに直接ロールバックを行い、私のリポジトリ層とJPAの間の依存関係を紹介しています。

新しいコードオプション3:

changeProcessModel(); 
messages = ProcessValidator.validate(process); 
if (messages.hasNoErrors()) { 
    messages.addInfoMessage("Process was updated succesfully"); 
} else { 
    processDao.refresh(process); 
} 
return messages; 

このコードはかなりいいようだが、それが適切にリフレッシュする必要がプロセスエンティティの関係に設定するCascadeType.REFRESHに依存しません。

例えば、processDao.clear();またはprocessDao.rollback();でも可能ですが、processDaoの範囲が全体でentityMangerに増加します。それが非常にきれいな方法であるかどうかはわかりません。

これについてのご意見はありますか?

答えて

0

あなたのドメイン内の永続性については、ご存じの方が少なくてもよいでしょう。だからではなく、私は、次の解決策を示唆しているモデルの一部としてそれを見てのドメインモデルのためのサービスとして、永続性を見てについての考えに沿って:

  • ドメインは常に、一貫性のある状態にしておく必要がありますが、
  • だから;モデルに入ってくる変更(サービスからのもの、あなたの持つUI)は、将来のモデルが検証されていることを知らずにモデルを変更することはできません。
  • 意味:現在のモデルは常に一貫しています。

式:Future model = CurrentModel.PerformChanges()。Validated();

どうすればいいですか?作業の種類の単位を使用している可能性があります。 (http://martinfowler.com/eaaCatalog/unitOfWork.html) ドメインオブジェクトが変更され、検証されるたびに、変更されたイベントが発生します。ユニット・オブ・ワーク・マネージャーは、それらのイベントをフェッチして、そのものがデータベースに格納されていることを確認します。変更が検証されない場合、イベントは発生せず、モデルは「無効」とマークされます。要求分離モードで作業するため、これは問題ではありません。共有ドメインモデルで作業する場合、変更はドメインにロールバックされなければなりません!

これはおそらく解決策の中で最も学術的なアプローチですが、おそらく、ディスカッションを開始するのに役立ちます。これらの状況で何をすべきか...

関連する問題