首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Hibernate事件侦听器-回滚

问Hibernate事件侦听器-回滚
EN

Stack Overflow用户
提问于 2012-08-28 05:28:40
回答 2查看 4.1K关注 0票数 6

我实现了一个Hibernate事件侦听器,如下所示:

代码语言:javascript
复制
public class AuditListener implements PostInsertEventListener {
  private static final long serialVersionUID = -966368101369878522L;

  @Override
  public void onPostInsert(PostInsertEvent event) {
    if (event.getEntity() instanceof Auditable) {
      StatelessSession session = null;
      try {
        session = event.getPersister().getFactory().openStatelessSession();
        Auditable auditableEntity = (Auditable)event.getEntity();
        session.beginTransaction();
        session.insert(new AuditTrail(auditableEntity.getClass().getSimpleName(),
            auditableEntity.getId(), auditableEntity.getStatus(),
            auditableEntity.getLastModified()));
        session.getTransaction().commit();
      } catch (HibernateException he) {
        System.out.println("Horrible error: " + he.getMessage());
        session.getTransaction().rollback();
      } finally {
        if (session != null) {
          session.close();
        }
      }
    }
  }
}

它所做的就是在插入任何Auditable对象之后立即将一个AuditTrail对象插入到数据库中。

当在持久化Auditable对象的事务期间出现任何类型的异常情况时,我遇到的问题就出现了:事务回滚,但我仍然插入了一条AuditTrail记录。

我试着改变这一点:

代码语言:javascript
复制
StatelessSession session = event.getPersister().getFactory().openStatelessSession();

如下所示:

代码语言:javascript
复制
Session session = event.getSession();

但是,当我尝试使用该会话时,它会导致堆栈跟踪,并以消息Session is closed结束。

问题似乎是,事件在事务中间触发,在导致回滚的异常情况之前触发,并且由于事件侦听器必须使用自己的会话,因此它也不会回滚。

有什么方法可以确保事件侦听器的操作也被回滚吗?我是否刚刚选择了在事务中过早发生的事件?在回滚发生的最后一个点之后,是否有一些我应该捕获的事件,从而确保在发生回滚时不会触发AuditTrail的插入?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-01-22 00:22:02

由于一直没有人回复,我一直在自己研究,我最初的解决方案如下:

代码语言:javascript
复制
public class AuditListener implements PostInsertEventListener {
  private static final long serialVersionUID = -966368101369878522L;

  @Override
  public void onPostInsert(PostInsertEvent event) {
    if (event.getEntity() instanceof Auditable) {
      Session session = null;
      try {
        session = event.getPersister().getFactory().getCurrentSession();
        Auditable auditableEntity = (Auditable)event.getEntity();
        session.save(new AuditTrail(auditableEntity.getClass().getSimpleName(),
            auditableEntity.getId(), auditableEntity.getStatus(),
            auditableEntity.getLastModified()));
      } catch (HibernateException he) {
        System.out.println("Horrible error: " + he.getMessage());
        session.getTransaction().rollback();
      }
    }
  }
}

请注意,我从PostInsertEvent的SessionFactoryImplementor调用了"getCurrentSession()“。我不确定这是不是一个潜在的危险策略,我也不确定保留这个rollback()调用是否有意义,但它似乎是有效的,没有其他人提供了更好的解决方案。

票数 7
EN

Stack Overflow用户

发布于 2017-08-11 02:20:00

我最近遇到了一个非常类似的问题。这些问题几年前就被问过了,但我认为这个答案可能会对其他人有所帮助。

当在持久化可审计对象的事务期间出现任何类型的异常情况时,我遇到的问题就出现了:事务回滚,但我仍然插入了一条AuditTrail记录。

在我看来,真正的问题是,当事务没有提交时,onPostInsert甚至不应该被解雇。

这被证明是hibernate中PostInsertEventListener的一个bug (8年了!)2006至2014年)。参考:https://hibernate.atlassian.net/browse/HHH-1582

为了向后兼容,他们通过引入新的PostCommitInsertEventListener修复了这个问题。因此,我们现在应该使用PostCommitInsertEventListener (对于hibernate >= v4.3.5),并且只有在成功提交事务时才应该触发onPostInsert

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12149870

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档