Java Hibernate:在beforeCommit中确定实例是否为新实例(保存后,instance.id!=null)

Java Hibernate:在beforeCommit中确定实例是否为新实例(保存后,instance.id!=null),java,spring,hibernate,grails,Java,Spring,Hibernate,Grails,有没有办法确定域实例在beforeCommit回调中是否是新的 上下文:一个grails应用程序(2.2.1版),它在下面使用spring和hibernate 用例: 每当给定类型(父级)或其子级的实例“以重大方式”更改时,我们需要向外部系统发送消息,例如父级属性更改、父级获得“批准”的新子级等。在同一事务中,可能会有许多事件触发父级的消息,我们只需要为每个家长、每个事务发送一条消息 我们实现了spring TransactionSynchronization,以便在beforeCommit中获

有没有办法确定域实例在beforeCommit回调中是否是新的

上下文:一个grails应用程序(2.2.1版),它在下面使用spring和hibernate

用例: 每当给定类型(父级)或其子级的实例“以重大方式”更改时,我们需要向外部系统发送消息,例如父级属性更改、父级获得“批准”的新子级等。在同一事务中,可能会有许多事件触发父级的消息,我们只需要为每个家长、每个事务发送一条消息

我们实现了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
}
@覆盖
void beforeCommit(布尔只读){
def transactionObjects=ApplicationContextHolder.applicationContext.sessionFactory.currentSession.transaction.transactionContext.persistenceContext。
List changedObjects=transactionObjects.findAll{
it.key.isDirty()| | isNewInstance(it)
}.collect{it.key}
//在这里做事
}
但是,我们无法找到确定实例是否为新实例的内置方法。isDirty仅适用于更新。 我们尝试使用EntityEntry.previousStatus,我们认为它只在新实例中为null,但测试表明,同一对象在两个后续beforeCommit调用中的previousStatus=null(这对我们的目的没有用处)

为我们工作的黑客:

  • 向域类(isNewInstance)添加临时布尔值

  • 在“beforeInsert”事件中将其设置为true

  • 并在提交前的最后清除它

但是,真的没有内置的HibernateAPI吗? (我们不能使用instance.id==null,因为它是在调用save()之后,并且该id将在持久化但尚未提交的对象中设置)

编辑:

假设:根据实例是否为新实例,Hibernate最终必须发出不同的SQL(插入与更新)。我知道它根据是否有ID生成SQL,然后将其放在事务的后面,因此不能将空ID用作指示符

问题:
但是hibernate是否在内部某个地方保存了这些信息,如果是这样,它是否提供了一个公共API?

GORM提供了一些方法,您可以在插入和更新实例时覆盖这些方法来实现自定义功能

此处的文档:

假设父对象是域对象,您可以只在插入前
或插入后
上实现功能,仅当对象是新创建的时才会调用该功能


另一方面,当对现有实例进行更新时,
beforeUpdate
将被调用。

使用afterInsert()方法难道还不够吗?如果我们使用afterInsert/update/Delete,我们(1)将其严格限制为gorm(2)将在子域类和父域类中都有调用(3)将在对象树中的每个更改中触发一个事件,例如父更改及其两个子更改将导致3个事件,我们只应发送一个。谢谢,但我们正在寻找一种方法,以beforeCommit或类似的方式执行此操作。我提到了“黑客”,我们使用beforeInsert将实例标记为新实例,并在beforeCommit中使用它,但我们希望避免它。请参阅我对卡米尔·米科拉伊克齐克(Kamil Mikolajczyk)对上述问题的评论的回答。