Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/jenkins/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Grails中奇怪的afterInsert/afterUpdate循环_Grails_Gorm - Fatal编程技术网

Grails中奇怪的afterInsert/afterUpdate循环

Grails中奇怪的afterInsert/afterUpdate循环,grails,gorm,Grails,Gorm,我有一个Note域类,当保存一个新的Note时,我需要为它创建一个notevent,为后代记录该Note已经创建注释有一组注释事件,每个注释事件跟踪它所属的注释 注释类: class Note { String noteText Date dateCreated static hasMany = [events : NoteEvent] } class NoteEvent { Date dateCreated String type stat

我有一个
Note
域类,当保存一个新的Note时,我需要为它创建一个
notevent
,为后代记录该Note已经创建<代码>注释有一组
注释事件
,每个
注释事件
跟踪它所属的
注释

注释
类:

class Note {
    String noteText
    Date dateCreated

    static hasMany = [events : NoteEvent]
}
class NoteEvent {
    Date dateCreated
    String type

    static belongsTo = [note : Note]
}
notevent
类:

class Note {
    String noteText
    Date dateCreated

    static hasMany = [events : NoteEvent]
}
class NoteEvent {
    Date dateCreated
    String type

    static belongsTo = [note : Note]
}
为了在创建便笺时处理新的
NoteEvents
的保存,我使用了
afterInsert
,因为我到处都在保存便笺实例(每次保存新便笺后都要有特定的事件创建代码,这将是重复和耗时的),显然,
beforeensert
并没有处理
Note
的持久化实例-对于
notevent
来说,它的
Note
没有任何内容

所以现在我的
注释
课程是:

class Note {
    String noteText
    Date dateCreated

    static hasMany = [events : NoteEvent]

    def afterInsert = {
        def event = new NoteEvent(type: "CREATED")
        addToEvents(event)
        save()
    }
}
但当其中一个笔记被更新时,我还需要创建一个
notevent
,这就是混乱、沮丧和严重缺乏咖啡的原因。为了在注释更新时将新的“更新的”
notevent
附加到注释上,我明智地决定再次使用
afterUpdate
,以避免在需要更新
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()
。但在“after”事件中,这是对
save()
的第二次调用。因此,当我第一次保存一个新实例并调用
afterInsert
时,刚保存的实例会立即再次保存,这会导致触发
afterUpdate
事件,现在我有两个便笺事件:一个是我刚保存便笺时的“创建”事件,另一个是“创建”时的“更新”事件其中一个使便笺再次保存


我不清楚在这种情况下使用“before”事件会有什么帮助。我还可以怎么做呢?

可能有一种方法可以做到这一点,可以使用
beforeirt
beforeUpdate
,因为这不需要保存
注释
实例。像这样进行二次更新/插入的典型方法是将
与NewSession一起使用,但在这种情况下,我不确定这是否有意义,因为这更多是为了创建一个独立的对象,您需要在新会话中重新加载
注释。没那么糟,但没什么表现

一种方法是删除集合并直接保存
notevent
实例:

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
}
课堂笔记{
字符串注释文本
创建日期
设置getEvents(){
NoteEvent.findAllByNote(此)
}
def afterInsert(){
新建NoteEvent(类型:“已创建”,注意:this).save()
}
def afterUpdate(){
新建NoteEvent(类型:“已更新”,注意:this).save()
}
}
类注释事件{
创建日期
字符串类型
附注
}

您失去了级联,因此您希望删除事务服务方法中的
Note
实例,以便可以删除其关联的
notevent
s。但这才是解决整个问题的办法。只需删除
afterInsert
afterUpdate
回调,并在事务性服务方法中完成所有工作(创建、更新和删除)。每当您执行多个数据库更新时,您都应该以事务方式进行更新,以便所有更新都成功或失败。这也满足了您的抗混乱要求,因为所有的工作都封装在服务中。

您实际上可以使用
beforeist
beforeUpdate
方法。这是因为
addTo*
方法不要求
Note
成为持久化实例

注释
保存时,
注释事件
将保存,因为
注释事件
是在
注释
保存在
更新前
方法之前添加的。有关详细的解释,请查看

我能够让以下两个
Note
类按照我认为您希望的方式工作。我确实遇到了一个问题,在更新
Note
时,会添加两个
notevent
对象。我可以通过确保控制器的更新方法是使用
noteInstance.save()
而不是
noteInstance.save(flush:true)
来解决这个问题

如果您想要更精简的版本,
addTo*
方法知道要添加什么类型的对象,您只需使用
notevent的
Map
构造函数即可

class Note {
    String noteText
    Date dateCreated

    static hasMany = [events : NoteEvent]

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

    def beforeUpdate = {
        addToEvents(type: "UPDATED")
    }
}
“因为我正在到处保存便笺实例”

我能问一下你在哪里救他们吗?我会避免将域实例保存在控制器中。如果你把它们保存得到处都是,那么你的整体设计可能值得一看

就个人而言,我倾向于创建某种Notes服务,如果可能的话,我将集中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()   
    }

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

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


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

Hmm……我同意使用集中式CRUD方法可以更容易地修改由各种持久性事件触发的行为。但出于我的目的(这里有很多现有代码,需要移动大量的工作),在域clas上使用
之前
之后
事件