我是hibernate的新手,我对错误处理和持久性工作流程有疑问。我有以下遗留代码。
public void doPersist(Contact out){
contactValidator.validationOne(out);
entityManager.persist(out);
contactValidator.validationTwo(out);
contactValidator.validationThree(out);
}
ContactValidator
是一个用于验证Contact
的类,它会在每个验证方法中抛出多个业务异常。我不喜欢方法doPersist
的构造方式。为什么它首先调用entityManager.persist
然后验证对象?如果某些验证方法中存在异常,则应回滚数据。 Hibernate如何在已经调用persist时回滚数据?
答案 0 :(得分:1)
我个人并不关心如何编写doPersist
方法,因为我可以看到几种更清洁的替代品,避免使用这种多余的方法。
要回答您的具体问题,回滚的神奇之处在于交易的运作方式。事务只不过是一系列作为单个工作单元执行的操作,必须遵循原子,一致,隔离和持久(例如ACID)。
当事务处于活动状态且尚未提交时,如果抛出异常,则异常处理会告知事务忘记了它被告知要执行的操作。
Session session = sessionFactory.openSession();
try {
session.getTransaction().begin();
// do whatever work you want to do here
session.getTransaction().commit();
}
catch ( Throwable t ) {
if ( session.getTransaction().isActive() ) {
session.getTransaction().rollback();
}
throw t;
}
finally {
session.close();
}
所以在这段代码中,即使事务正在尝试提交并抛出异常,catch子句也会看到它处于活动状态并将事务回滚,从而告诉数据库丢弃所有刚刚被问到的工作表演。
现在,我想触摸您的 ContactValidator 。
我的猜测是你的ContactValidator
与Bean验证的方式密切相关。它基本上会查看bean的状态,并确保没有任何不一致的期望,如果是这样,则断言有异常。
将hibernate-validator
与hibernate-core
结合使用时,您可以免费获得bean验证,因为Hibernate会插入验证器框架并对以下事件执行验证操作
如您所见,开箱即用的 post 事件支持没有。这是有道理的,因为您通常希望在实际保存或更新数据库行之前满足约束。这就是为什么我发现你的第二和第三次接触验证方法很奇怪。
除此之外,如果您确实需要一些插入后或更新后验证,您可以使用在PostInsertEvent
上注册的自定义Hibernate侦听器轻松绑定到现有的bean验证器侦听器以进行这些操作。 PostUpdateEvent
组调用bean验证。