gpt4 book ai didi

java - 在 Spring 中处理 @Transactional 方法期间的异常

转载 作者:行者123 更新时间:2023-12-02 02:08:16 24 4
gpt4 key购买 nike

我试图找出如何结合 Spring 的 @Transactional 最好地处理持久性(以及可能的其他)异常。在这篇文章中,我将仅举一个用户注册的简单示例,该示例可能会由于重复的用户名而导致 DataIntegrityViolationException

我尝试过以下一些方法,但它们对我来说并不是很满意:

1。天真的方法:只捕获异常

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 事务包装器中的服务方法之外。

2。退出前刷新 EntityManager

在我的服务方法末尾显式调用 EntityManager 上的 flush。这将强制写入数据库并因此触发异常。然而,它可能效率低下,因为我现在必须注意不要在请求期间无缘无故地多次刷新。我也最好永远不要忘记它,否则异常就会消失得无影无踪。

3。创建两个服务类

@Transactional方法放在一个单独的spring bean中,并在主服务中 try catch 它们。这很奇怪,因为我必须小心地将代码的一部分放在 A 处,将另一部分放在 B 处。

4。在 Controller 中处理 DataIntegrityViolationException

只是...不。 Controller 不负责处理数据库中的异常(huehuehue)。

5。不要捕获 DataIntegrityViolationException

我在网络上看到了一些资源,特别是与 Hibernate 结合使用时,表明捕获此异常是错误的,应该在保存之前检查条件(即通过手动查询检查用户名是否存在)。这在并发场景中不起作用,即使有事务也是如此。是的,您将获得事务的一致性,但当“其他人先来”时,您仍然会遇到 DataIntegrityViolationException。因此,这不是一个可接受的解决方案。

7。不要使用声明式事务管理

使用 Spring 的 TransactionTemplate而不是@Transactional。这是唯一有点令人满意的解决方案。然而,它的使用比“仅仅在方法上抛出@Transactional”要“笨重”,甚至 Spring 文档似乎也在插入您使用@Transactional。

我想要一些关于如何最好地处理这种情况的建议。我上次提出的解决方案有更好的替代方案吗?

最佳答案

我在我的项目中使用以下方法。

  1. 自定义注释。
public @interface InterceptExceptions
{
}
  • Spring 上下文中的 Bean 和切面。
  • <beans ...>
    <bean id="exceptionInterceptor" class="com.example.ExceptionInterceptor"/>

    <aop:config>
    <aop:aspect ref="exceptionInterceptor">
    <aop:pointcut id="exception" expression="@annotation(com.example.InterceptExceptions)"/>
    <aop:around pointcut-ref="exception" method="catchExceptions"/>
    </aop:aspect>
    </aop:config>
    </beans>
    import org.aspectj.lang.ProceedingJoinPoint;

    public class ExceptionInterceptor
    {

    public Object catchExceptions(ProceedingJoinPoint joinPoint)
    {
    try
    {
    return joinPoint.proceed();
    }
    catch (MyException e)
    {
    // ...
    }
    }
    }
  • 最后是用法。
  • @Service
    @Transactional
    public class SomeService
    {
    // ...

    @InterceptExceptions
    public SomeResponse doSomething(...)
    {
    // ...
    }
    }

    关于java - 在 Spring 中处理 @Transactional 方法期间的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50150647/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com