java - Hibernate:在beforeCommit中判断一个实例是否是新的(保存后,instance.id != null)

标签 java spring hibernate grails

有没有办法在 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:
  • 将 transient boolean 值添加到域类 (isNewInstance)
  • 在“beforeInsert”事件中将其设置为 true
  • 并在 beforeCommit
  • 结束时清除它

    但是真的没有内置的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/

    相关文章:

    hibernate - 用于单向1:n关系的Grails GORM数据库映射

    java - Android:与其他应用程序上的 Intent 共享位图

    java - 按主题从 Twitter 用户构建网络图

    java ;试图建立一个接受多个客户端连接的服务器

    java - Spring @ConfigurationProperties 绑定(bind)在测试中失败

    java - jpa查询错误:the multi-part identifier could not be bound

    java - 将 JPanel 添加到 JFrame 时遇到问题

    java - Spring JPA + CRUD - 自定义查询不允许 _ 字符?

    java - Spring 数据mongodb : How to define cursor limit in findAll method

    hibernate - 名称以 "ID"结尾的成员变量被 grails 强制成为一个 id( hibernate )