我实现了一个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对象之后立即将一个AuditTrail对象插入到数据库中。
当在持久化Auditable对象的事务期间出现任何类型的异常情况时,我遇到的问题就出现了:事务回滚,但我仍然插入了一条AuditTrail记录。
我试着改变这一点:
StatelessSession session = event.getPersister().getFactory().openStatelessSession();如下所示:
Session session = event.getSession();但是,当我尝试使用该会话时,它会导致堆栈跟踪,并以消息Session is closed结束。
问题似乎是,事件在事务中间触发,在导致回滚的异常情况之前触发,并且由于事件侦听器必须使用自己的会话,因此它也不会回滚。
有什么方法可以确保事件侦听器的操作也被回滚吗?我是否刚刚选择了在事务中过早发生的事件?在回滚发生的最后一个点之后,是否有一些我应该捕获的事件,从而确保在发生回滚时不会触发AuditTrail的插入?
发布于 2013-01-22 00:22:02
由于一直没有人回复,我一直在自己研究,我最初的解决方案如下:
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()调用是否有意义,但它似乎是有效的,没有其他人提供了更好的解决方案。
发布于 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
https://stackoverflow.com/questions/12149870
复制相似问题