【问题标题】:Is it possible to persist new Entities in a @Pre/PostPersist Listener?是否可以在 @Pre/PostPersist 侦听器中保留新实体?
【发布时间】:2011-12-26 21:11:02
【问题描述】:

我正在尝试设置我的休眠应用程序以在每次创建 Activity 实体时持久保存一个新的 Notification 实体 - 目前,我尝试过的所有 Notification 都无法静默持久(在记录但永远不会执行 sql)。

任何人都可以确认甚至可以在 Hibernate pre/postPersist 侦听器中持久化其他实体吗?

我已阅读文档:

回调方法不得调用 EntityManager 或 Query 方法!

但我已经阅读了其他几个似乎表明这是可能的讨论主题。

作为参考,我尝试的两种方法是:

  1. @PrePersist 方法 - 设置 Activity 和 Notification 之间的 cascade.ALL 关系,并在 PrePersist 方法中简单地创建一个新的 Notification 并将其链接到正在创建的 Activity希望Notification 能坚持下去。

  2. @PostPersist 方法 - 使用 @Configurable 和 ListenerClass,连接到服务中并创建新的 Notification 实体,然后显式调用 entityManger 持久化

有人可以确认我正在尝试什么吗?

【问题讨论】:

    标签: java hibernate spring jpa


    【解决方案1】:

    为什么必须在@PrePersist 或@PostPersist 函数中坚持Notification?以下代码应保留两个实体:

    @Entity
    public class Activity implements Serializable {
       @OneToOne(cascade={CascadeType.PERSIST})
       private Notification notification;
    }
    
    @Entity
    public class Notification implements Serializable { }
    
    @Stateless
    public class MrBean implements MrBeanInterface {
       @PersistenceContext()
       private EntityManager em;
    
       public void persistActivity() {
          Activity act = new Activity();
          act.setNotification(new Notification());
          em.persist(act);
       }
    }
    

    更新:您可以尝试在 Activity 的构造函数中创建链接,如下所示:

    @Entity
    public class Activity implements Serializable {
       @OneToOne(cascade={CascadeType.PERSIST})
       private Notification notification;
    
       public Activity() {
          this.notification = new Notification();
       }
    }
    
    @Entity
    public class Notification implements Serializable { }
    
    @Stateless
    public class MrBean implements MrBeanInterface {
       @PersistenceContext()
       private EntityManager em;
    
       public void persistActivity() {
          Activity act = new Activity();
          em.persist(act);
       }
    }
    

    需要注意的一点是,我认为您不能使用@PostPersist。更准确地说,您必须在持久化Activity 之前将Notification 链接到Activity,以便cascade={CascadeType.PERSIST} 工作。

    【讨论】:

    • 谢谢 - 我需要在 pre/postPersist 方法中添加通知,因为我想确保每次创建活动时,也会创建相应的通知。如果您认为 Notification 是需要保证的审计对象,那么第一个解决方案存在有人可能会调用 em.persist(act); 的风险;代码库中的其他任何地方(批处理/操作类或任何其他服务类),除非他们也添加通知代码,否则我们不会得到审计。第二种解决方案是我在原始帖子中为我的方法 1) 尝试的方法,但无声无息地失败了。
    • @rhinds 我刚刚更新了我的答案。您可以在 Activity 的构造函数中创建链接。
    • 谢谢,我会试试这个 - 虽然它看起来仍然不理想,因为在坚持之前仍然可以编辑。似乎 pre-persist 应该是做这种操作的正确位置,例如,我们之前使用 prePersist 方法设置所有对象的修改日期,这意味着修改日期永远不能手动更改或覆盖
    • 使用构造函数的问题是 Hibernate 在加载对象时使用它来实例化对象 - 由于需要使用其他信息创建通知,因此会导致问题(每当 hibernate 加载时重新创建新通知实体)
    • 然而,一直在玩弄它的 prePersist&Cascade 方法现在正在工作(似乎它最初可能没有工作,因为 Hibernate 使用自身的外键创建了 Notification 表,它永远不会满足并且只是在 prePersist 中默默地失败) - 所以会接受这个答案,因为它描述了我用于 @PrePersist & Cascade 设置的相同细节我正在使用..
    【解决方案2】:

    您可以使用StatelessSession 接口在 Hibernate 事件侦听器(插入、更新、刷新等)中保留其他实体。但我不知道这是否也适用于严格的仅 JPA 代码(EntityManagerFactory 和 EntityManager)。

    【讨论】:

    • 是的,它是特定于实现的,但是 Hibernate 和 EclipseLink 都有类似的东西。
    • 谢谢 - 这是否适合运行时持续存在?我注意到文档将其称为批处理操作接口,并且不使用任何一级/二级缓存..
    猜你喜欢
    • 2018-08-23
    • 1970-01-01
    • 2012-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-26
    • 1970-01-01
    相关资源
    最近更新 更多