Spring Data JPA + Hibernate:永远不会到达Transactional方法内的catch块 [英] Spring Data JPA + Hibernate : catch block inside a Transactional method is never reached

查看:116
本文介绍了Spring Data JPA + Hibernate:永远不会到达Transactional方法内的catch块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我们的Spring Data JPA + Hibernate应用程序中,有多种方法在同一个事务中具有多个JPA操作-以下是其中一种spring服务方法的代码/配置.

In our Spring Data JPA + Hibernate application, there are various methods having multiple JPA operations inside the same transaction - below is the code/configuration on one of the spring service methods.

@Transactional(rollbackFor=MyAppException.class)
public void updateCustomerprofile(String customerKey) throws MyAppException{
    try{
    CustomerId customerIdObj = customerIdRepository.findOne(customerKey);
    customerIdObj.setCreatedUser("<loggedin-user>");
     // more logic here
    customerIdObj = customerIdRepository.save(customerIdObj);
    }catch(DataAccessException dae){
        //this catch block is never reached even if there is an exception while saving because of JPA flusheing at the end of transaction
        throw new MyAppException(dae);
    }

}

已观察到,即使在保存记录时抛出异常,执行也永远不会到达catch块-这是因为JPA在事务结束时刷新了.

It's been observed that the execution will never reach the catch block even if there is an exception thrown while saving the record - and it is because JPA flushes at the end of the transaction.

此捕获块应确切放置在什么地方?

Where exactly should this catch block be placed?

我们应该在Web层(bean)上捕获DataAcccessException吗?

Should we be catching DataAcccessException on the web layer (bean)?

如果是这样,我们是否不将数据层依赖项放到Web层上?

If so, are we not taking the datalayer dependencies on to web layer?

如果我必须将DataAccessException包装到我的应用程序特定的异常中,该怎么办?

If I have to wrap DataAccessException into my application specific exception, how do I do it?

请提出建议.

推荐答案

此处的问题是代码中没有引发异常,而是在容器提交事务时引发异常(另请参见

The problem here is that the exception is not thrown within your code, but when the container commits the transaction (see also this answer). To avoid using bean-managed transactions, you can:

  • 通过EntityManager.flush()同步持久性上下文,
  • 使用带有@AroundInvoke批注的EJB拦截器,该批注将开始,提交和回滚事务(与BMT相似的方法),或者
  • 使用@TransactionAttribute(REQUIRES_NEW)将应该引发异常的代码包装起来.
  • Synchronize the persistence context via EntityManager.flush(),
  • Use an EJB interceptor with the @AroundInvoke annotation which begins, commits and rollbacks the transaction (similar approach to BMT), or
  • Wrap the code which is supposed to throw the exception in a method with @TransactionAttribute(REQUIRES_NEW).

另请参见此线程,其中进一步介绍了有关REQUIRES_NEW方法的一些细节.

See also this thread, where some details about the REQUIRES_NEW approach are further explained.

这篇关于Spring Data JPA + Hibernate:永远不会到达Transactional方法内的catch块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆