代码之家  ›  专栏  ›  技术社区  ›  jb.

关闭java.sql.connection时是否应捕获引发的异常

  •  14
  • jb.  · 技术社区  · 17 年前

    Connection.close() 可能扔 SqlException 但我一直认为忽略任何此类异常是安全的(而且我从未见过不忽略它们的代码)。

    通常我会写:

     try{
        connection.close();
     }catch(Exception e) {}
    

     try{
        connection.close();
     }catch(Exception e) {
         logger.log(e.getMessage(), e); 
     }
    

    问题是:

    1. 这是一种不好的做法吗(并且在忽略这些例外情况时有任何人遇到问题)。
    2. 什么时候? 连接。关闭() 不会引发任何异常。
    3. 如果情况不好,我该如何处理这个异常。

    评论:

    我知道丢弃异常是邪恶的,但我只会引用关闭连接时抛出的异常(正如我所看到的,这在本例中相当常见)。

    有人知道什么时候 连接。关闭() 可以扔东西吗?

    12 回复  |  直到 7 年前
        1
  •  13
  •   anjanb    17 年前

    实际上,您所做的是(几乎)最佳实践:-)这是我在Spring的jdbcutils.java中看到的。因此,您可能需要添加 另一个拦网。

    /**
     * Close the given  ResultSet and ignore any thrown exception.
     * This is useful for typical finally blocks in manual  code.
     * @param resultSet the  ResultSet to close
     * @see javax.resource.cci.ResultSet#close()
     */
    private void closeResultSet(ResultSet resultSet) {
      if (resultSet != null) {
        try {
          resultSet.close();
        }
        catch (SQLException ex) {
          logger.debug("Could not close  ResultSet", ex);
        }
        catch (Throwable ex) {
          // We don't trust the  driver: It might throw RuntimeException or Error.
          logger.debug("Unexpected exception on closing  ResultSet", ex);
        }
      }
    }
    
        2
  •  12
  •   Bill K    17 年前

    总的来说,我浪费了很多时间,因为人们抛弃了这样的例外。

    我建议遵循一些基本规则,但有例外:

    如果您绝对确定不会对选中的异常产生问题,那么只捕获该异常,并对不需要处理该异常的确切原因进行注释。(睡眠会引发一个中断的例外,除非你真的对它感兴趣,否则它总是可以被忽略的,但老实说,这是我通常忽略的唯一情况——即使这样,如果你永远也得不到它,记录它的成本是多少?)

    如果您不确定,但可能偶尔会得到它,那么捕获并记录一个堆栈跟踪,以便在它引起问题时找到它。同样,只捕获需要捕获的异常。

    如果您看不到任何可以抛出已检查异常的方法,请捕获该异常并将其作为未检查异常重新抛出。

    如果您确切地知道是什么导致了异常,那么捕捉它并记录下具体的原因,在这种情况下,如果您非常清楚是什么导致了异常(如果您还没有使用log4j或其他东西,那么您可能会提到记录它的类),那么就不需要堆栈跟踪。

    听起来,您的问题可能属于最后一类,对于这种捕获,永远不要执行您编写的操作(异常E),总是执行特定的异常,以防引发未经检查的异常(错误参数、空指针等)。

    更新: 这里的主要问题是选中的异常是ungood。他们所使用的唯一高度使用的语言是Java。它们在理论上是整洁的,但在实际操作中,它们会导致这种捕获和隐藏的行为,这种行为除了未经检查的异常情况外,是无法得到的。

    很多人都评论过我说过有时候隐藏他们是可以的。具体来说,我能想到的一个例子是:

    try {
        Thread.sleep(1000);
    catch (InterruptedException e) {
        // I really don't care if this sleep is interrupted!
    }
    

    我想我觉得使用InterruptedException没问题的主要原因是,使用InterruptedException首先是对选中的异常模式的滥用,它传递的是睡眠的结果,而不是指示异常情况。

    这样做更有意义:

    boolean interrupted=Thread.sleep(1000);
    

    但是,当他们首次创建Java时,他们非常自豪自己的新检查异常模式(可以理解的是,它在概念上非常简洁——实际上只是失败了)。

    我无法想象另一个情况是可以接受的,所以也许我应该把它列为 这个 忽略异常可能有效的单一情况。

        3
  •  6
  •   matt b    17 年前

    至少, 总是 总是 总是 记录正在捕获但未执行的异常。

    沉默地捕捉到的例外情况,如果没有最微小的窥视就被吞下,则是最糟糕的。

        4
  •  3
  •   Jeremy    17 年前

    我个人喜欢你第二个至少记录错误的想法。因为您正在捕获异常,所以理论上可以捕获除SQL异常之外的其他内容。我不确定会发生什么或发生多罕见(如内存不足的异常等),但抑制所有错误对我来说似乎并不正确。

    如果您想抑制错误,我只会对您知道应该那样处理的非常具体的错误进行抑制。

    假设情况:如果您的SQL有一个打开的事务,并且由于这个原因关闭连接导致了一个异常,那么您想抑制这个错误吗?甚至抑制sqleexceptions也有点危险。

        5
  •  1
  •   Guido    17 年前

    你必须处理这个例外。这不是一个坏习惯。假设您在关闭DABATASE连接之前丢失了网络。它可能会抛出异常。

    这是罕见的吗?对。我想这就是所谓的例外,这并不是忽视它的理由。记住,如果失败,它就会失败。

    您还应该考虑此时是否可能有空连接(它将导致nullPointerException)。

    if (connection != null) {
       try { 
          connection.close(); 
       } catch (SQLException sqle) { 
          logger.log(e.getMessage(), e); 
       }
    }
    
        6
  •  1
  •   Robin    17 年前

    在一个理想的世界里,你不应该对一个例外什么都不做,当然,在一个理想的世界里,你也不会得到一个例外8-)

    因此,您必须检查各种选项的影响。

    只记录:数据库操作都完成了,只剩下清理资源了。如果此时发生异常,它很可能对执行的工作没有影响,因此记录错误就足够了。当然,如果在日志记录期间发生错误,那么您基本上必须处理失败的数据库操作,而这些操作实际上并没有失败。

    空处理程序:数据库操作全部完成,只剩下清理资源了。如果此时发生异常,它很可能对执行的工作没有影响,因此该方法成功返回。下一个数据库访问可能会遇到同样的问题,但它应该发生在事务的开始,在那里它将正确地失败,然后得到适当的处理。如果问题已经自行解决,那么就没有任何迹象表明有任何问题。

    在finally块中放置close()操作以确保清理发生,这是一个非常典型的场景,因为我们不希望任何其他故障阻止资源清理。如果没有发生任何错误,那么当方法的操作成功完成时,您的方法不应该失败。在这种情况下,空异常处理是非常正常的。

    当然,意见会有所不同。

        7
  •  1
  •   Fábio    17 年前

    您还可以引发RuntimeException:

    try {
        connection.close();
     } catch(Exception e) {
         throw new RuntimeException(e); 
     }
    

    您不必更改方法签名,稍后将能够使用exception.getcause方法查找问题的原因。

        8
  •  1
  •   Brian Agnew    17 年前

    注意 Apache Commons DButils 提供了一个 closeQuietly() 方法,可以使用该方法避免将代码与“多余”捕获混淆。注意,我不是在提倡接受例外,而是为了这个 close() 我认为这是可以接受的。

        9
  •  0
  •   a-sak    17 年前

    根据我的经验,忽略一个例外从来不是一个好主意。 相信我,生产支持工程师和分析师会感谢你一吨,如果你记录了例外。

    此外,如果您使用的是正确的日志框架,那么异常对性能的影响将为零或最小。

        10
  •  0
  •   SWD    17 年前

    如果这是一个“永远不会发生的错误”的情况,那么我将重新引发一个异常,希望没有人能抓住它。
    如果这是其他情况,我可能会记录下来

        11
  •  0
  •   Thorbjørn Ravn Andersen    16 年前

    如果你能处理它,那么就这样做(如果它是意外的,就记录下来)。如果您不能处理它,那么重新正确地处理它,以便上面的一些代码可以处理它。

    无声地吞咽异常会为修改代码的人留下关键信息。

        12
  •  0
  •   Sankar    13 年前

    最好在关闭与数据库的连接时处理异常。因为,在代码的某个时间点,如果您试图访问语句或结果集对象,那么它将自动引发异常。所以,最好处理这个异常。

    推荐文章