0

我有一个Note域类,当一个新的笔记被保存时,我需要为它创建一个NoteEvent,记录该笔记已创建的后代。Note有一个 的集合NoteEvents,每个NoteEvent都跟踪Note它属于哪个。

Note班级:

class Note {
    String noteText
    Date dateCreated

    static hasMany = [events : NoteEvent]
}

NoteEvent班级:

class NoteEvent {
    Date dateCreated
    String type

    static belongsTo = [note : Note]
}

为了NoteEvents在创建便笺时处理新的保存,我使用afterInsert,因为我在各处保存便笺实例(在每次保存新便笺后使用特定的事件创建代码将是重复且耗时的),并且beforeInsert显然没有处理Noteyet 的持久实例 - 没有任何东西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在其中一个笔记更新时创建一个,这就是混乱和沮丧以及严重缺乏咖啡的地方。要在更新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()实例。但在“之后”事件的情况下,这是对save(). 因此,当我第一次保存一个新实例并afterInsert调用它时,刚刚保存的实例会立即再次保存,这会导致afterUpdate事件被触发,现在我有两个笔记事件:我刚刚保存时的“创建”一个笔记,以及“更新”的笔记,当“创建”笔记导致笔记再次被保存时。

我不清楚使用“之前”事件如何在这种情况下有所帮助。我还能怎么做?

4

3 回答 3

4

您实际上可以使用beforeInsertbeforeUpdate方法。这是因为该addTo*方法不需要Note是持久化实例。

NoteEvent在保存时Note保存,因为在方法中保存NoteEvent之前添加了。查看文档以获得更长的解释。NotebeforeUpdateaddTo*

我能够让以下两个Note课程按照我认为您希望的方式工作。我确实遇到了一个问题,即在更新Note两个NoteEvent对象时会添加。我可以通过确保控制器的更新方法使用noteInstance.save()而不是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并且beforeUpdate因为那些不需要保存Note实例。像这样进行二次更新/插入的典型方法是使用withNewSession,但在这种情况下,我不确定它是否有意义,因为这更多地用于创建独立对象,并且您需要Note在新会话中重新加载. 没那么糟糕,但性能不佳。

一种方法是删除集合并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的 s。但这确实是整个问题的解决方案。只需删除afterInsertafterUpdate回调并在事务服务方法中完成所有工作(创建、更新和删除)。每当您进行多个数据库更新时,您都应该以事务方式进行更新,以便它们全部成功或全部失败。这也满足了您的抗混乱要求,因为所有工作都封装在服务中。

于 2013-01-10T01:42:29.210 回答
2

“因为我正在到处保存笔记实例”

我能问一下你在哪里保存它们吗?我会避免将您的域实例保存在您的控制器中。如果您将它们保存在所有地方,则可能值得查看您的整体设计。

就个人而言,我更倾向于创建某种 NoteService,如果可能的话,我会在其中集中 CRUD 操作。一个示例服务是:

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

    .... 
}

我更喜欢上述方法的原因是,如果您发现自己想要做更多的事情来响应这些事件并避免重复代码,它可以更好地扩展。

另一种方法可能是进行登录过滤器。但是,如果您在许多地方保存笔记实例,这可能会很棘手/混乱。

否则我会考虑使用上面提到的 beforeInsert/beforeUpdate 函数。

于 2013-01-10T05:17:32.880 回答