Hibernate事件监听器 – 回滚

我实现了一个像这样的Hibernate事件监听器:

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对象后立即将Auditable对象插入数据库。

我遇到的问题是,在事务期间出现任何类型的exception情况,持续存在Auditable对象:事务被回滚,但我仍然会插入AuditTrail记录。

我试着转过身来:

 StatelessSession session = event.getPersister().getFactory().openStatelessSession(); 

进入这个:

 Session session = event.getSession(); 

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

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

有没有办法确保事件监听器的操作也回滚? 我刚刚选择了在交易中过早发生的事件吗? 是否有一些我应该捕获的事件发生在可能发生回滚的最后一点之后,从而确保在发生回滚时不会触发AuditTrail的插入?

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

 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(); } } } } 

请注意,我从PostInsertEventSessionFactoryImplementor调用“ getCurrentSession() ”。 我不确定这是否是一个潜在危险的策略,我也不确定是否有意义保持rollback()调用,但它似乎运行,没有其他人提供更好的解。 你去吧

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

我遇到的问题是,在事务期间出现任何类型的exception情况,持续存在Auditable对象:事务被回滚,但我仍然会插入AuditTrail记录。

在我看来,真正的问题是,当事务未提交时, onPostInsert甚至不会被触发。

事实certificate这是hibernate中PostInsertEventListener一个错误(8年!从2006年到2014年)。 参考: https : //hibernate.atlassian.net/browse/HHH-1582

为了向后兼容,他们通过引入新的PostCommitInsertEventListener解决问题。 所以我们现在应该使用PostCommitInsertEventListener (对于hibernate> = v4.3.5),只有在事务成功提交时才会触发onPostInsert