【问题标题】:Hibernate, Spring, @Transactional - surround with try/catch?Hibernate、Spring、@Transactional - 用 try/catch 包围?
【发布时间】:2011-07-19 17:48:26
【问题描述】:

我正在使用 Spring 3 和 Hibernate 3.6 开发 Web 应用程序。我对@Transactional 注释和代码结构有一些疑问。

-> 当我使用@Transactional(Spring 的事务管理)时,在调用@Transactional-annotated 方法时是否必须用try/catch 包围它们?

例如,当我得到一个加载、更改和返回一个对象的方法时,我从另一个类调用它:我必须用 try/catch 包围调用吗?可能出问题了,没有返回对象,数据库连接失败..我不知道。

直到现在,我认为@Transactional 关心所有可能发生的异常,并在发生错误时回滚此事务中的每个操作。 但如果发生这种情况,我必须以某种方式通知用户。当我在 try-block 中调用 transactional-method 并回滚时,catch 块被激活? 我可以告诉用户“确实出了问题”。否则可能不会通知用户?

或者检查是否有返回的对象(if/else)就足够了,那么我不需要try/catch? 我是新手,我想听听其他人如何构建他们的代码。谢谢你:-)

【问题讨论】:

    标签: java hibernate spring exception transactional


    【解决方案1】:

    感谢您回答我。我通读了链接(spring 文档),发现以下内容:

    “但是,DAO 会抛出普通的 HibernateException(这是未经检查的,因此不必声明或捕获),这意味着调用者只能将异常视为通常是致命的 - 除非他们想依赖 Hibernate 自己的异常层次结构。 如果不将调用者与实现策略联系起来,就不可能捕获特定原因,例如乐观锁定失败。这种权衡对于基于 Hibernate 和/或不需要任何特殊异常处理的应用程序来说可能是可以接受的。”

    我的 DAO 基于 Plain Hibernate 3 API,所以如果我理解正确,我的 DAO 只会抛出普通的 HibernateExceptions。它们是未经检查的,不必申报或捕获。 如果出现问题,使用 @Transactional 会回滚整个操作。

    为了确保一切都按预期工作,我必须将我的 DAO 与我的应用程序代码联系得更紧密。例如,我可以检查一个对象是否被归还。 (如果为空 - 否则) 我还可以捕获异常,记录它并通知用户确实出了问题并且他的事务没有工作。

    所以在这一点上,我仍然在想,这取决于交易: 如果我可以处理结果,则一切正常 - 如果没有,我可以通知用户。

    当未指定事务返回结果时,我可以使用 try/catch 来捕获 HibernateException。但是那个时候交易还回滚吗?我想,捕获 HibernateException 可以避免回滚事务。 我仍然不知道该怎么办。 :-(

    不幸的是,除此之外,我不明白 MVC 异常处理 (@ExceptionHandler) 与此有什么关系。有一个处理异常的表,但我没有找到 HibernateException。 或者你认为它会与这个一起工作:@ExceptionHandler(HibernateException.classs)?你也说过你不建议以这种方式处理异常。

    【讨论】:

      【解决方案2】:

      Handling exceptions 在 Spring 中使用 HandlerExceptionResolvers 和 @ExceptionHandlers 非常简单。我倾向于专门使用@ExceptionHandler。

      您可以使用@ExceptionHandler 来处理特定异常,而不是自己在 try-catch 块中处理它。

      如果用户想要一个未找到的资源,而您想要发送 404。

      @ExceptionHandler(NotFoundException.class)
      @ResponseStatus(HttpStatus.NOT_FOUND)
      public void handleNotFoundException(NotFoundException exc) {
        // log something.
      }
      

      如果出现服务器问题,您想发送 500

      @ExceptionHandler(SomeException.class)
      public void handleException(SomeException exc, WebRequest request, HttpServletResponse response) {
          response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Sorry dude, my server broke");
      }
      

      您还应该严格处理异常。一般来说,你不应该这样做@ExceptionHandler(Exception.class),我也相信它可以按顺序工作,所以如果你确实处理了一般异常,它应该是类中的最后一个方法。

      【讨论】:

      • 你对代码示例是认真的吗?永远不应该像那样吞下异常。这样代理就没有机会检测到异常并回滚事务。我希望你的意思是这样的:catch(SomeException exc) { throw new IllegalStateException(exc); }
      • @Sean 这只是伪代码。我希望他不会接受例外,除非他有充分的理由这样做。
      • 这就是为什么我要问,而不是投反对票。你应该说清楚,周围有很多新手
      • 感谢您的回答。第二个伪代码正是我在我的问题中提到的。我并不是要在事务方法中捕获异常,而是要围绕事务注释方法的调用。所以我不清楚答案:我可以那样做,但我不应该这样做?如果事务回滚,我如何通知用户?
      • 您可以使用 Sean 的回答中提到的异常翻译来生成标准异常(在春季 DataAccessException 或其他),并使用 @ExceptionHandler 捕获异常并通知用户。我更新了答案以显示示例。
      【解决方案3】:

      Spring使用的关键特性是Exception Translation

      依靠异常翻译来生成您的客户端层理解的异常,并在可能的情况下仅在此处使用 try/catch。

      【讨论】:

        猜你喜欢
        • 2014-11-02
        • 2017-10-06
        • 2012-03-29
        • 2021-03-17
        • 1970-01-01
        • 2019-07-01
        • 2011-05-04
        • 1970-01-01
        • 2019-07-10
        相关资源
        最近更新 更多