java在Spring的@Transactional方法期间处理异常
我试图找出如何结合Spring的@Transactional
来最好地处理持久性(以及潜在的其他)异常。
在这篇文章中,我将以一个简单的用户注册为例,它可能会由于重复的用户名而导致DataIntegrityViolationException
我试过以下几件事,但都不太满意:
一,。天真的方法:抓住例外
val entity = UserEntity(...)
try {
repo.save(entity)
} catch (e: DataIntegrityViolationException) {
// not included: some checks for which constraint failed
throw DuplicateUsername(username) // to be handled by the controller
}
这在@Transactional
方法中不起作用,因为在提交事务之前不会发生持久性异常,这在spring事务包装器中我的服务方法之外发生
二,。退出前刷新EntityManager
在我的服务方法末尾的EntityManager
上显式调用flush
。这将强制写入数据库,从而触发异常。然而,这可能是低效的,因为我现在必须注意,在一个请求过程中,不要无缘无故地多次刷新。我也最好永远不要忘记它,否则例外会消失在空气中
三,。上两堂服务课
将@Transactional
方法放在一个单独的Springbean中,并在主服务中尝试捕获它们。这很奇怪,因为我必须注意将代码的一部分放在A位置,另一部分放在B位置
四,。在控制器中处理DataIntegrityViolationException
只是。。。不可以。控制器没有处理数据库异常的业务(色调)
五,。不要抓住DataIntegrityViolationException
我在网上看到了一些资源,尤其是与Hibernate结合使用的资源,它们表明捕获此异常是错误的,应该在保存前检查条件(即通过手动查询检查用户名是否存在)。这在并发场景中不起作用,即使在事务中也是如此。是的,您将获得与事务的一致性,但当“其他人先到”时,您仍将获得DataIntegrityViolationException
。因此,这不是一个可接受的解决方案
七,。不要使用声明性事务管理
使用Spring的^{@Transactional
。这是唯一稍微令人满意的解决方案。然而,它比“仅仅在方法上抛出@Transactional
”要“笨拙”得多,甚至Spring文档似乎也在推动您使用@Transactional
我想要一些关于如何最好地处理这种情况的建议。除了我上次提出的解决方案,还有更好的选择吗
共 (0) 个答案