Connection.close()
可能会抛出SqlException
,但我一直认为忽略任何此类异常是安全的(我从未见过不会忽略它们的代码)。
通常我会写:
try{
connection.close();
}catch(Exception e) {}
或
try{
connection.close();
}catch(Exception e) {
logger.log(e.getMessage(), e);
}
问题是:
Connection.close()
确实抛出任何异常。 评论:
我知道丢弃异常是邪恶的,但我只是在关闭连接时抛出的异常(而且我已经看到这种情况在这种情况下相当普遍)。
有人知道Connection.close()
什么时候可能扔东西吗?
答案 0 :(得分:13)
实际上,你所做的是(几乎)最佳实践:-)这是我在Spring的JdbcUtils.java中看到的。所以,你可能想要添加 另一个Catch区块。
/**
* 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);
}
}
}
答案 1 :(得分:12)
总的来说,我已经浪费了几天人们抛弃这样的例外情况。
我建议遵循以下几条基本规则:
如果你绝对确定你永远不会导致检查异常的问题,抓住JUST该异常并准确评论为什么你不需要处理它。 (Sleep会抛出一个InterruptedException,除非你真的对它感兴趣,否则总是可以忽略它,但说实话,这是我经常忽略的唯一情况 - 即使在那种情况下,如果你从未得到它,记录它的成本是多少?)
如果您不确定,但偶尔可以得到它,请捕获并记录堆栈跟踪,以便在发生问题时可以找到它。再次,只捕获您需要的例外。
如果您没有看到任何方式可以抛出已检查的异常,请将其捕获并将其作为未经检查的异常重新抛出。
如果你确切地知道导致异常的原因,抓住它并准确记录原因,在这种情况下你真的不需要堆栈跟踪,如果你非常清楚是什么导致它(你可能会提到这个类的如果您还没有使用log4j或其他东西,请记录它。
听起来你的问题会落到最后一个类别,对于这种类型的捕获,永远不会做你写的(异常e),总是做一些特定的异常以防万一抛出一些未经检查的异常(错误的参数,空指针,...)
更新:这里的主要问题是Checked Exceptions是不合适的。他们存在的唯一高度使用的语言是Java。它们在理论上是整洁的,但是在行动中它们会导致捕捉和隐藏的这种行为,而你没有得到未经检查的异常。
很多人都评论过这样一个事实:我说隐藏它们有时是好的。具体而言,我能想到的一个案例是:
try {
Thread.sleep(1000);
catch (InterruptedException e) {
// I really don't care if this sleep is interrupted!
}
我认为我觉得这种用法的主要原因是好的,因为这种使用InterruptedException首先是滥用已检查的异常模式,它正在传达睡眠的结果,而不是指示异常情况。
拥有以下内容会更有意义:
boolean interrupted=Thread.sleep(1000);
但是当他们第一次创建Java时,他们为他们新的检查异常模式感到非常自豪(可以理解的是,它在概念上非常简洁 - 只在实践中失败)
我无法想象另一个可以接受的情况,所以也许我应该将其列为 单例,忽略异常可能是有效的。
答案 2 :(得分:6)
至少,始终 始终 始终 记录您正在捕获但未采取行动的异常。
在没有最微小的窥视的情况下,悄悄地捕获的异常是最糟糕的。
答案 3 :(得分:3)
我个人喜欢你至少记录错误的第二个想法。因为你正在捕获异常,理论上可以捕获除SQL异常之外的其他东西。我不确定会发生什么或者多么罕见(比如内存异常等),但是压制所有错误对我来说似乎并不合适。
如果你想抑制错误,我只会对你知道应该以这种方式处理的非常具体的错误。
假设情况:如果你的sql有一个打开的事务,并且关闭连接导致了一个exceptino因为那个,你想要抑制那个错误怎么办?即使压制SQLExceptions也可能有点危险。
答案 4 :(得分:1)
您必须处理异常。这不是一个坏习惯。想象一下,在关闭dabatase连接之前你丢失了网络。它可能会抛出异常。
难得一见吗?是。我想这就是所谓的例外,这不是忽视它的理由。请记住,如果它失败了,它就会失败。
您还应该考虑此时是否可以建立空连接(它会导致NullPointerException)。
if (connection != null) {
try {
connection.close();
} catch (SQLException sqle) {
logger.log(e.getMessage(), e);
}
}
答案 5 :(得分:1)
在一个理想的世界里,你永远不应该对异常做任何事情,当然,在一个理想的世界里,你永远不会得到例外8 - )
因此,您必须检查各种选项的影响。
仅记录:数据库操作全部完成,除了清理资源外别无选择。如果此时发生异常,则很可能对执行的工作没有影响,因此记录错误应该足够了。当然,如果在日志记录期间发生错误,那么您基本上必须处理实际上没有失败的失败的数据库操作。
空处理程序:数据库操作全部完成,除了清理资源外别无选择。如果此时发生异常,则很可能对执行的工作没有影响,因此该方法成功返回。下一个数据库访问可能会遇到同样的问题,但它应该在事务开始时发生,它将正确地失败然后得到适当的处理。如果问题已经解决,那么就没有迹象表明出现了任何问题。
将finally()操作放在finally块中是一种非常典型的方案,以确保发生清理,因为我们不希望任何其他故障阻止资源清理。如果没有发生错误,那么当其操作成功完成时,您的方法不应该失败。在这种情况下,空异常处理是很正常的。
当然意见会有所不同。
答案 6 :(得分:1)
您还可以抛出RuntimeException:
try {
connection.close();
} catch(Exception e) {
throw new RuntimeException(e);
}
您不必更改方法签名,并且稍后可以使用Exception.getCause方法来查找问题的原因。
答案 7 :(得分:1)
请注意,Apache Commons DButils提供了closeQuietly()
方法,您可以使用该方法避免因“冗余”捕获而使代码混乱。请注意,我不提倡吞咽异常,但对于close()
这种情况,我认为这通常是可以接受的。
答案 8 :(得分:0)
根据我的经验,忽略异常绝不是一个好主意。 相信我,如果您记录了异常,那么生产支持工程师和分析师会感谢您一吨。
此外,如果您使用正确的日志记录框架,则异常的性能影响为零或最小。
答案 9 :(得分:0)
如果这是一个“永远不会发生的错误”的情况,那么我将重新抛出一个异常并希望没有人抓住它。
如果这是任何其他情况,我可能会记录它
答案 10 :(得分:0)
如果你可以处理它,那么这样做(如果是意外的话,记录它)。如果你无法处理它,那么请正确地重新抛出它,以便上面的一些代码可以处理它。
悄悄吞咽异常会遗漏关键信息,以便该人修复代码。
答案 11 :(得分:0)
在关闭与数据库的连接时处理异常是一种更好的做法。因为,在代码的某个时间点,如果您尝试访问语句或结果集对象,那么它将自动引发异常。所以,最好处理异常。