关闭 java.sql.Connection 时是否应该捕获抛出的异常
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/248149/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Should I catch exceptions thrown when closing java.sql.Connection
提问by jb.
Connection.close()may throw SqlException, but I have always assumed that it is safe to ignore any such exceptions (and I have never seen code that does not ignore them).
Connection.close()可能会 throw SqlException,但我一直认为忽略任何此类异常是安全的(而且我从未见过不忽略它们的代码)。
Normally I would write:
通常我会写:
try{
connection.close();
}catch(Exception e) {}
Or
或者
try{
connection.close();
}catch(Exception e) {
logger.log(e.getMessage(), e);
}
The question is:
问题是:
- Is it bad practice (and has anyone had problems when ignoring such exceptions).
- When
Connection.close()does throw any exception. - If it is bad how should I handle the exception.
- 这是不好的做法(并且在忽略此类异常时是否有人遇到过问题)。
- 什么
Connection.close()时候抛出任何异常。 - 如果不好,我应该如何处理异常。
Comment:
评论:
I know that discarding exceptions is evil, but I'm reffering only to exceptions thrown when closing a connection (and as I've seen this is fairly common in this case).
我知道丢弃异常是邪恶的,但我只是指关闭连接时抛出的异常(正如我所见,在这种情况下这很常见)。
Does anyone know when Connection.close()may throw anything?
有谁知道什么时候Connection.close()可以扔东西?
采纳答案by anjanb
Actually, what you're doing is (almost) best practice :-) here's what I saw in Spring's JdbcUtils.java. So, you might want to add another Catch block.
实际上,您正在做的是(几乎)最佳实践 :-) 这是我在 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);
}
}
}
回答by Bill K
In general, I've had days wasted by people throwing away exceptions like that.
总的来说,我已经因为人们扔掉这样的异常而浪费了几天时间。
I recommend following a few basic rules with exceptions:
除了例外,我建议遵循一些基本规则:
If you are ABSOLUTELY SURE you will NEVER cause a problem with a checked exception, catch JUST that exception and comment exactly why you don't need to handle it. (Sleep throws an InterruptedException that can always be ignored unless you actually are interested in it, but honestly this is the only case I usually ignore--even at that, if you never get it, what's the cost of logging it?)
如果您绝对确定您永远不会因已检查的异常而导致问题,请仅捕获该异常并准确评论为什么您不需要处理它。(睡眠会抛出一个 InterruptedException ,除非你真的对它感兴趣,否则它总是可以被忽略,但老实说,这是我通常忽略的唯一情况——即使在那种情况下,如果你永远不会得到它,记录它的成本是多少?)
If you are not sure, but you may get it occasionally, catch and log a stack trace just so that if it is causing a problem, it can be found. Again, catch only the exception you need to.
如果您不确定,但有时可能会得到它,请捕获并记录堆栈跟踪,以便在它引起问题时可以找到它。同样,只捕获您需要的异常。
If you don't see any way the checked exception can be thrown, catch it and re-throw it as an unchecked exception.
如果您看不到任何可以抛出已检查异常的方法,请捕获它并将其作为未检查异常重新抛出。
If you know exactly what is causing the exception, catch it and log exactly why, you don't really need a stack trace in this case if you are very clear as to what's causing it (and you might mention the class that's logging it if you're not already using log4j or something.
如果您确切知道导致异常的原因,捕获它并准确记录原因,在这种情况下,如果您非常清楚导致异常的原因(并且您可能会提到记录它的类,如果你还没有使用 log4j 或其他东西。
It sounds like your problem would fall into the last category, and for this kind of a catch, never do what you wrote (Exception e), always do the specific exception just in case some unchecked exception is thrown (bad parameters, null pointer, ...)
听起来你的问题属于最后一类,对于这种捕获,永远不要做你写的(异常 e),总是做特定的异常,以防抛出一些未经检查的异常(错误参数,空指针, ...)
Update:The main problem here is that Checked Exceptions are ungood. The only highly used language they exist in is Java. They are neat in theory, but in action they cause this behavior of catch and hide that you don't get with unchecked exceptions.
更新:这里的主要问题是检查异常是不好的。它们存在的唯一高度使用的语言是 Java。它们在理论上是整洁的,但实际上它们会导致这种捕获和隐藏行为,而未经检查的异常则不会出现这种行为。
A lot of people have commented on the fact that I said that hiding them is okay sometimes. To be specific, the one case I can think of is:
很多人评论我说有时隐藏它们是可以的。具体来说,我能想到的一种情况是:
try {
Thread.sleep(1000);
catch (InterruptedException e) {
// I really don't care if this sleep is interrupted!
}
I suppose the main reason I feel this use is okay is because this use of InterruptedException is an abuse of the checked exception pattern in the first place, it's communicating the result of a sleep more than indicating an exception condition.
我想我觉得这种使用还可以的主要原因是因为 InterruptedException 的这种使用首先是对检查异常模式的滥用,它传达了睡眠的结果而不是指示异常情况。
It would have made much more sense to have:
拥有以下内容会更有意义:
boolean interrupted=Thread.sleep(1000);
But they were very proud of their new checked exception pattern when they first created Java (understandably so, it's really neat in concept--only fails in practice)
但是当他们第一次创建 Java 时,他们为他们的新检查异常模式感到非常自豪(可以理解,它在概念上非常简洁——只是在实践中失败了)
I can't imagine another case where this is acceptable, so perhaps I should have listed this as thesingle case where it might be valid to ignore an exception.
我无法想象这是可以接受的另一种情况,所以也许我应该将其列为忽略异常可能有效的单一情况。
回答by matt b
At the very minimum, alwaysalwaysalwayslog exceptions that you are catching and not acting on.
在最起码,总是永远永远记录异常,你正赶上,而不是作用于。
Silently caught exceptions that are swallowed without the tiniest peep are the worst.
悄悄捕获的异常是最糟糕的。
回答by Jeremy
I personally like your second idea of at least logging the error. Because you're catching Exception, it's theoretically possible to catch something other than a SQL Exception. I'm not sure what could happen or how rare (like out of memory exceptions, etc) but supressing all errors doesn't seem right to me.
我个人喜欢你至少记录错误的第二个想法。因为您正在捕获异常,所以理论上可以捕获 SQL 异常以外的其他内容。我不确定会发生什么或有多罕见(如内存不足异常等),但对我来说抑制所有错误似乎并不正确。
If you want to suppress errors, I would do it only to very specific ones you know should be handled that way.
如果您想抑制错误,我只会对您知道应该以这种方式处理的非常具体的错误进行处理。
Hypothecial situation: what if your sql had an open transaction, and closing the connection caused an exceptino because of that, would you want to suppress that error? Even suppressing SQLExceptions might be a little dangerous.
假设情况:如果您的 sql 有一个打开的事务,并且因此关闭连接导致异常,您想抑制该错误吗?即使抑制 SQLExceptions 也可能有点危险。
回答by Guido
You have to handle the exception. It is not a bad practice. Imagine you lost the network just before closing the dabatase connection. It will probably throw the exception.
您必须处理异常。这不是一个坏习惯。想象一下,您在关闭 dbatase 连接之前丢失了网络。它可能会抛出异常。
Is it rare ? Yes. I suppose that's what they are called exceptions and that is not a reason to ignore it. Remember that if it could fail, it will fail.
稀有吗?是的。我想这就是他们所谓的例外,这不是忽略它的理由。请记住,如果它可能失败,它就会失败。
You should also think about whether it is possible to have a null connection at this point (it would cause a NullPointerException) or not.
您还应该考虑此时是否可能有一个空连接(它会导致 NullPointerException)。
if (connection != null) {
try {
connection.close();
} catch (SQLException sqle) {
logger.log(e.getMessage(), e);
}
}
回答by Robin
In an ideal world, you should never do nothing on an exception, of course, in an ideal world, you would never get an exception either 8-)
在理想的世界中,您永远不应该对异常无所作为,当然,在理想的世界中,您也永远不会遇到异常 8-)
So, you have to examine the impacts of the various options.
因此,您必须检查各种选项的影响。
Log only: Database operations are all finished, nothing left to do but clean up the resources. If an exception occurs at this point, it most likely has no impact on the work performed, so logging the error should suffice. Of course, if an error occurs during logging, then you basically have to handle failed database operation that didn't actually fail.
Log only:数据库操作全部完成,只剩下清理资源了。如果此时发生异常,它很可能对执行的工作没有影响,因此记录错误就足够了。当然,如果在日志记录过程中发生错误,那么您基本上必须处理实际上并未失败的失败数据库操作。
Empty handler: Database operations are all finished, nothing left to do but clean up the resources. If an exception occurs at this point, it most likely has no impact on the work performed, so the method returns successfully. The next database access may run into the same problem, but it should occur at the start of a transaction, where it will rightly fail and then get handled appropriately. If the problem has fixed itself, then there will be no indication that anything ever went wrong.
Empty handler:数据库操作全部完成,只剩下清理资源了。如果此时发生异常,很可能对执行的工作没有影响,因此该方法成功返回。下一次数据库访问可能会遇到同样的问题,但它应该发生在事务开始时,它会正确地失败,然后得到适当的处理。如果问题已自行解决,则不会有任何问题出现的迹象。
It is a pretty typical scenario to put a close() operation(s) in a finally block to ensure that cleanup occurs, since we don't want any other failures to inhibit the resource cleanup. If no error has occurred, then your method should not fail when its operation has successfully completed. In this case, empty exception handling is quite normal.
将 close() 操作放在 finally 块中以确保清理发生是一个非常典型的场景,因为我们不希望任何其他故障阻止资源清理。如果没有发生错误,那么您的方法在其操作成功完成后应该不会失败。在这种情况下,空异常处理是很正常的。
Of course opinions will vary.
当然,意见会有所不同。
回答by Fábio
You could also throw a RuntimeException:
你也可以抛出一个 RuntimeException:
try {
connection.close();
} catch(Exception e) {
throw new RuntimeException(e);
}
You won't have to change your method signature and will be able to use the Exception.getCause method later on to find the cause of the problem.
您不必更改您的方法签名,并且可以稍后使用 Exception.getCause 方法来查找问题的原因。
回答by Brian Agnew
Note that Apache Commons DButilsprovides a closeQuietly()method, that you can use to avoid cluttering your code with 'redundant' catches. Note I'm not advocating swallowing exceptions, but for this close()scenario I think it's generally acceptable.
请注意,Apache Commons DButils提供了一种closeQuietly()方法,您可以使用该方法避免因“冗余”捕获而使代码混乱。注意我不提倡吞下异常,但对于这种close()情况,我认为它通常是可以接受的。
回答by Thorbj?rn Ravn Andersen
If you can handle it, then do so (and log it if it was unexpected). If you cannot handle it, then rethrow it properly so some code above can handle it.
如果您可以处理它,那么就这样做(如果意外,请记录下来)。如果您无法处理它,则正确地重新抛出它,以便上面的一些代码可以处理它。
Silently swallowing exceptions is leaving out crucial information for the person to fix the code.
默默地吞下异常会遗漏人们修复代码的关键信息。
回答by Sankar
Its a better practice to handle the exception at the time of closing the connection to the database. Because, at later some point of time in your code, if you are trying to access the statement or resultset objects then it will automatically raise an exception. So, Better to handle the exception.
在关闭与数据库的连接时处理异常是更好的做法。因为,稍后在您的代码中的某个时间点,如果您尝试访问语句或结果集对象,那么它会自动引发异常。所以,最好处理异常。

