0

ドメインクラスがあり、新しいメモが保存されたら、メモが作成されたことを後世に記録Noteする を作成する必要があります。のコレクションがあり、それぞれが所属先を追跡します。NoteEventNoteNoteEventsNoteEventNote

Noteクラス:

class Note {
    String noteText
    Date dateCreated

    static hasMany = [events : NoteEvent]
}

NoteEventクラス:

class NoteEvent {
    Date dateCreated
    String type

    static belongsTo = [note : Note]
}

NoteEventsメモが作成されたときに new の保存を処理するafterInsertために、私は を使用していました。これは、メモのインスタンスをあちこちに保存しているためです (新しいメモを保存するたびに、特定のイベント作成コードを作成するのは反復的で時間がかかります)。 )、そしてbeforeInsert明らかにまだ永続化されたインスタンスを扱ってNoteいません — がNoteEventその として持つものは何もありませんnote

だから今私のNoteクラスは:

class Note {
    String noteText
    Date dateCreated

    static hasMany = [events : NoteEvent]

    def afterInsert = {
        def event = new NoteEvent(type: "CREATED")
        addToEvents(event)
        save()
    }
}

しかしNoteEvent、これらのメモの 1 つが更新されたときにも作成する必要があります。ここで、混乱と落胆、コーヒーの大幅な不足が発生します。更新さNoteEventれたときに新しい「更新」をメモに添付するために、私は見事に次のように決定しました。インスタンスafterUpdateを更新する必要があるたびに、イベント作成コードがアプリ全体に散らばるのを避けるために、もう一度 を使用します。Note

だから今、Note私は持っています:

class Note {
    String noteText
    Date dateCreated

    static hasMany = [events : NoteEvent]

    def afterInsert = {
        def event = new NoteEvent(type: "CREATED")
        addToEvents(event)
        save()
    }

    def afterUpdate = {
        def event = new NoteEvent(type: "UPDATED")
        addToEvents(event)
        save()
    }
}

メモのコレクションに新しいイベントを追加するために、動的addTo()メソッドを使用していますが、これsave()にはインスタンスの が必要です。しかし、「後」イベントの場合、これは への 2 回目の呼び出しsave()です。したがって、最初に新しいインスタンスを保存してafterInsertが呼び出されると、保存されたばかりのインスタンスがすぐに再度保存され、afterUpdateイベントが発生します。これで、2 つのノート イベントが発生します。メモ、および「作成された」メモによってメモが再度保存されたときの「更新された」メモ。

この状況で代わりに「前」イベントを使用することがどのように役立つかは、私には明らかではありません。他にどうすればこれを行うことができますか?

4

3 に答える 3

4

beforeInsertおよびbeforeUpdateメソッドを実際に使用できます。これは、メソッドが永続化されたインスタンスであるaddTo*必要がないためです。Note

がメソッドに保存される前に が追加されるため、が保存されるNoteEventときにも保存されます。より長い説明については、ドキュメントを参照してください。NoteNoteEventNotebeforeUpdateaddTo*

次のNoteクラスの両方を、あなたが望んでいると思う方法で機能させることができました。更新時にNote2 つのNoteEventオブジェクトが追加されるという 1 つの問題に遭遇しました。noteInstance.save()コントローラーの update メソッドが の代わりに使用されていることを確認することで、これを修正できましたnoteInstance.save(flush:true)

class Note {
    String noteText
    Date dateCreated

    static hasMany = [events : NoteEvent]

    def beforeInsert = {
        def event = new NoteEvent(type: "CREATED")
        addToEvents(event)
    }

    def beforeUpdate = {
        def event = new NoteEvent(type: "UPDATED")
        addToEvents(event)
    }
}

より圧縮されたバージョンが必要な場合は、addTo*メソッドは追加されるオブジェクトのタイプを認識しており、Mapコンストラクターを使用できますNoteEvent

class Note {
    String noteText
    Date dateCreated

    static hasMany = [events : NoteEvent]

    def beforeInsert = {
        addToEvents(type: "CREATED")
    }

    def beforeUpdate = {
        addToEvents(type: "UPDATED")
    }
}
于 2013-01-10T03:26:33.483 に答える
3

インスタンスを保存する必要がないためbeforeInsert、おそらくこれを行う方法があります。このような二次更新/挿入を行う一般的な方法は使用することですが、この場合、それが意味をなすかどうかはわかりません。これは、独立したオブジェクトを作成するためのものであり、新しいセッションで再ロードする必要があるためです。 . それほど悪くはありませんが、パフォーマンスは高くありません。beforeUpdateNotewithNewSessionNote

これを行う 1 つの方法は、コレクションを削除してNoteEventインスタンスを直接保存することです。

class Note {
   String noteText
   Date dateCreated

   Set<NoteEvent> getEvents() {
      NoteEvent.findAllByNote(this)
   }

   def afterInsert() {
      new NoteEvent(type: "CREATED", note: this).save()
   }

   def afterUpdate() {
      new NoteEvent(type: "UPDATED", note: this).save()
   }
}

class NoteEvent {
   Date dateCreated
   String type
   Note note
}

カスケードが失われるNoteため、関連する を削除できるように、トランザクション サービス メソッドでインスタンスを削除する必要がありますNoteEvent。しかし、それは本当に問題全体の解決策です。afterInsertおよびコールバックを削除するだけafterUpdateで、トランザクション サービス メソッドですべての作業 (作成、更新、および削除) を実行できます。複数のデータベース更新を行うときは常に、すべてが成功するかすべて失敗するように、トランザクションとして実行する必要があります。これは、すべての作業がサービスにカプセル化されているため、クラッター防止の要件も満たしています。

于 2013-01-10T01:42:29.210 に答える
2

「ノート インスタンスをあちこちに保存しているため」

それらをどこに保存しているかお伺いしてもよろしいですか?ドメイン インスタンスをコントローラに保存することは避けたいと思います。それらをあちこちに保存している場合は、全体的なデザインを検討する価値があるかもしれません。

個人的には、可能であれば CRUD 操作を一元化できる NoteService のようなものを作成したいと考えています。サービスの例は次のとおりです。

class NoteService 
{
    Note create (String noteText)
    {
       Note note = new Note(noteText: noteText)  
                       .addToEvents(new NoteEvent(type: NoteEvent.CREATED))
                       .save()   
    } 

    Note update (int id, String noteText)
    {
       Note note = Note.findById(id)
       note.setNoteText(noteText)
       note.addToEvents(new NoteEvent(type: NoteEvent.UPDATED))
           .save()   
    }

    .... 
}

私が上記のアプローチを好む理由は、これらのイベントに対応してより多くのことを行いたいと思った場合にスケールしやすく、コードの重複を回避できるからです。

もう 1 つの方法は、フィルターでログを記録することです。ただし、メモのインスタンスを多くの場所に保存している場合、これは扱いにくい/面倒な場合があります。

それ以外の場合は、上記の beforeInsert/beforeUpdate 関数の使用を検討します。

于 2013-01-10T05:17:32.880 に答える