use*_*479 7 spring hibernate flush
我发生了最奇怪的事情,我无法弄明白为什么.描述这个的最好方法是提供一个简单的例子:
@Service
@Transactional
public class Foo{
public ModelAndView delete(@ModelAttribute("abc") Long id) {
ModelAndView mav = new ModelAndView();
try {
getDaoService().delete(id); //Calls Bar.delete()
} catch (final Exception e) {
// Add a custom error message to the mav for the user to see
mav.getModelMap().addAttribute(blah, blah);
}
return mav;
}
}
@Service
@Transactional
public class Bar {
public void delete(final E entity) throws HibernateException {
if (null != entity) {
try {
sessionFactory.getCurrentSession().delete(entity);
} finally {
sessionFactory.getCurrentSession().flush();
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
在这种特殊情况下,我试图删除一个具有约束违规的对象(ORA-02292).我希望删除失败,因为这个.当删除失败时,我希望向用户显示适当的自定义消息.
呼叫失败并显示以下内容,而不是向用户显示自定义消息:
org.springframework.transaction.UnexpectedRollbackException:事务回滚,因为它已被标记为仅回滚
当我使用调试器时,我可以看到错误被正确捕获,并且ModelAndView对象内部有自定义消息.所以,我不知道为什么在捕获和处理异常之后仍然会抛出异常.有谁有洞察为什么会这样?
在@Transactional注释上,您可以使用该noRollbackForClassName属性声明是否由于给定异常而回滚事务.你可以这样做.
@Service
@Transactional(noRollbackForClassName = "java.lang.Exception")
public class YourClass {
...
}
Run Code Online (Sandbox Code Playgroud)
但是,请注意,只是说它noRollbackForClassName = "java.lang.Exception"意味着它不会为任何异常(或其子类)回滚,因此它不是一个好习惯.
你应该做的是,找出实际抛出的异常(可能是打印出来的e.getClass().getName()),然后将该类名设置为noRollbackForClassName值.
理由是,这种情况正在发生,因为如果在尝试delete()时抛出某个异常,则当前事务会自动标记为仅回滚,如果尝试提交,则会抛出您看到的异常.传递此方法的方法是明确声明此特定异常不应导致回滚.
问题是因为一旦引发异常,Spring就会内部将tx标记为仅回滚。这与Java异常处理完全分开。您有几种选择:
RuntimeException;Spring仅在类型为tx时回滚它RuntimeException(请参见本页第10.5.3节)。 HibernateException扩展了RuntimeException,因此这就是为什么要获得回滚标记的原因。@Transactional(propagation=Propagation.REQUIRES_NEW)。然后,每个呼叫将在其自己的TX中运行,并且不会影响整体TX。noRollbackForClassName提到的风格venushka。但出于上述原因,请谨慎使用。| 归档时间: |
|
| 查看次数: |
8080 次 |
| 最近记录: |