我实现了一个像这样的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();
}
}
}
}
}
它只是在插入任何AuditTrail
对象后立即将Auditable
对象插入数据库。
我遇到的问题是,在事务期间出现任何异常情况时,Auditable
对象仍然存在:事务被回滚,但我仍然会插入AuditTrail
条记录。< / p>
我试着转过身来:
StatelessSession session = event.getPersister().getFactory().openStatelessSession();
进入这个:
Session session = event.getSession();
但是当我尝试使用该会话时,会导致堆栈跟踪以消息Session is closed
结束。
问题似乎是事件在事务中间触发,在导致回滚的异常情况之前触发,并且由于事件侦听器必须使用自己的会话,因此它也不会被回滚。
是否有某种方法可以确保事件监听器的操作也回滚?我刚刚选择了在交易中过早发生的事件吗?是否有一些我应该捕获的事件发生在可能发生回滚的最后一点之后,从而确保在发生回滚时不会触发AuditTrail
的插入?
答案 0 :(得分:6)
由于没有人回复,我一直在自己研究,我的初步解决方案如下:
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();
}
}
}
}
请注意,我正在getCurrentSession()
的{{1}}调用“PostInsertEvent
”。我不确定这是否是一个潜在危险的策略,我也不确定是否有意义保持SessionFactoryImplementor
呼叫,但似乎功能正常,没有其他人提供更好的解决方案。你去吧。
答案 1 :(得分:0)
我最近遇到了一个非常类似的问题。这些问题是几年前提出的,但我认为这个答案可能有助于其他人。
我遇到的问题是,在事务期间出现任何异常情况,持续存在Auditable对象:事务被回滚,但我仍然会插入AuditTrail记录。
在我看来,真正的问题是,print(df.loc[df['ID'] == '12'])
在未提交交易时甚至不会被解雇。
原来这是onPostInsert
在冬眠中的一个错误(从2006年到2014年8年!)。参考:https://hibernate.atlassian.net/browse/HHH-1582
为了向后兼容,他们通过引入新的PostInsertEventListener
来解决问题。所以我们现在应该使用PostCommitInsertEventListener
(对于hibernate&gt; = v4.3.5),只有在成功提交事务时才会触发PostCommitInsertEventListener