有没有办法在 beforeCommit 回调中确定域实例是否是新的?
上下文:一个 grails 应用程序 (v. 2.2.1),它在下面使用 spring 和 hibernate。
用例:
每当给定类型(父)或其子实例“以显着方式”发生变化时,我们需要向外部系统发送消息,例如Parent 属性发生变化,Parent 获得“已批准”的新子代等。可能有许多事件会触发同一事务中的父级消息 ,我们需要发送每个父级,每个事务只有一条消息 .
我们实现 spring TransactionSynchronization 以在 beforeCommit 中获得通知。我们得到“persistenceContext”,我们检查新实体或脏实体,然后聚合每个父级并在适当时发送通知。相关的代码片段:
@Override
void beforeCommit(boolean readOnly) {
def transactionObjects = ApplicationContextHolder.applicationContext.sessionFactory.currentSession.transaction.transactionContext.persistenceContext.
List<Object> changedObjects = transactionObjects.findAll {
it.key.isDirty() || isNewInstance(it)
}.collect { it.key }
// do stuff here
}
但是,我们无法找到一种内置方法来确定实例是否是新的。 isDirty 仅适用于更新。
我们尝试使用 EntityEntry.previousStatus,我们认为它只会对新实例为 null,但测试表明同一对象可以在两个后续的 beforeCommit 调用中具有 previousStatus = null(因此这对我们的目的没有用)。
对我们有用的 hack:
但是真的没有内置的hibernate API可用吗?
(我们不能使用 instance.id == null,因为它是在调用 save() 之后,并且 id 将设置在持久但尚未提交的对象中)。
编辑:
假设 :Hibernate 最终必须根据实例是否为新实例发出不同的 SQL(插入与更新)。我知道它会根据是否有 ID 生成 SQL,然后将其立即放在事务中,因此 null ID 不能用作指示符。
问题:
但是hibernate是否不会在内部某个地方保存这些信息,如果是这样,它不提供公共(public)API吗?
最佳答案
GORM 提供您在插入和更新实例时重写以实现自定义功能的方法。
此处的文档:http://grails.github.io/grails-doc/latest/guide/GORM.html#eventsAutoTimestamping
假设 Parent 是一个域对象,你可以在 beforeInsert
上实现你的功能。或 afterInsert
,仅当对象为 时才会调用新创建的 .beforeUpdate
另一方面,当现有实例有更新时会调用。
关于java - Hibernate:在beforeCommit中判断一个实例是否是新的(保存后,instance.id != null),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28829490/