0

私は現在、Grails Webアプリを実装しています。エンティティまたはトップレベルドメインオブジェクトがない限り、関連付けグラフの変更を「メモリ内」(つまりhttpセッション)で管理する必要がある複雑なフォームがいくつかあります。保存しました。

例えば

上から下へ:ドキュメント->カテゴリ->サブカテゴリ..。

要件:ドキュメント/カテゴリ/サブカテゴリへの変更は、ドキュメントが保存されるときのみ保存され、他の状況では保存されません。

私の最初のアプローチは、関連付けIDをhttpセッションに格納することでしたが、これは、セッションの状態を現在の永続的な状態と同期するDocumentController.updateアクションに多くの手がかりコードを含むことになります。

// update some abstract association
for (def Iterator it = documentInstance.association.iterator(); it.hasNext();)  {
  if (!session.association.contains(it.next().someEntity.id))  {
    it.remove()
  }
}

for (def roleTypeId in session.association)  {
  // add/update association
  ... 
}

カテゴリなどのデータを実際に変更する場合、手がかりコードはさらに悪化します。つまり、変更されたカテゴリオブジェクトは、最上位のエンティティを保存するときにデタッチ/再アタッチ/マージする必要があります。

このような長期にわたる作品についてのあなたの考えに非常に興味があります。

4

2 に答える 2

2

「長い会話」とも呼ばれるセッションごとのセッションパターンを使用できます。このように機能する grails webflow プラグインを試してください。または、Webflow がニーズに合わないと思われる場合は、自分で session-per-conversation を実装してください。

基本的な前提は、会話の開始時に新しい休止状態セッション (フラッシュ モード = 手動) を開き、それをユーザーの http セッションに保存することです。後続の各 http リクエストの開始時に、sessionFactory.getCurrentSession が会話の休止セッションを返すことを確認する必要があります。また、各リクエストの最後にこのセッションを切断して、リクエスト間の jdbc 接続を閉じることを忘れないでください。会話の最後に到達したら、セッションをフラッシュしてすべての変更を保持するか、フラッシュせずに閉じてキャンセルします。

Hibernate の Web サイト / Java Persistence with Hibernate の本には、これを行う方法に関する非常に優れた情報がありますが、grails には Webflow 以外にすぐに使用できるサポートはありません。私は SessionPerConversation プラグインを作成中ですが、非常に初期の段階です。私のアプローチは、grails 1.2.0 のソース コードを見て、.withNewSession の実装方法をコピーし、.withConversation、.endConversation、および .discardConversation のメソッドでコントローラーを装飾することでした。もう少し進んだら、State Your Biznessにコードを投稿する予定です。

これまでに出くわした落とし穴は...

  1. ユーザーが会話を終了しない場合、http セッションがタイムアウトするまで (jdbc 接続ではなく) hibernate セッションが開いたままになります。複数の会話をサポートしている場合、各ユーザーが複数の休止セッションを持つ可能性があり、使用率の高いサイトではメモリの問題が発生する可能性があります

  2. 自動セッションフラッシュに注意する必要があります。これは、id 生成に使用する戦略に応じてエンティティを新規作成する場合、またはトランザクション サービスを呼び出す場合に発生する可能性があります。

于 2010-01-27T09:53:19.673 に答える
0

いくつかの考え:

コードをコントローラーから切り離し、サービスに入れます。

サービスの静的な「transactional」プロパティをfalseに設定し、トランザクションを制御します。次のようになります。

class DocumentService {
    // take control from spring
    static transactional = false

    void updateMethod() {
        Document.withTransaction { transact ->
            // handle your business

            // problems? - you can always rollback without breaking anything
            transact.setRollbackOnly()
        }
    }
}

これにより、「defdocumentService」という行を使用してサービスをコントローラーに注入できます。サービス内のすべてのロジックを処理し、すべてをより徹底的にテストできます。

于 2010-01-21T12:24:49.560 に答える