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上使用之前
或之后
事件