问题
I have often come across situations like :-
try{
...
stmts
...
}
catch(Exception ex) {
...
stmts
...
} finally {
connection.close // throws an exception
}
which still needs a try - catch block inside finally.
What is the best practice to overcome this?
回答1:
Write a SQLUtils
class that contains static closeQuietly
methods that catch and log such exceptions, then use as appropriate.
You'll end up with something that reads like this:
public class SQLUtils
{
private static Log log = LogFactory.getLog(SQLUtils.class);
public static void closeQuietly(Connection connection)
{
try
{
if (connection != null)
{
connection.close();
}
}
catch (SQLExcetpion e)
{
log.error("An error occurred closing connection.", e);
}
}
public static void closeQuietly(Statement statement)
{
try
{
if (statement!= null)
{
statement.close();
}
}
catch (SQLExcetpion e)
{
log.error("An error occurred closing statement.", e);
}
}
public static void closeQuietly(ResultSet resultSet)
{
try
{
if (resultSet!= null)
{
resultSet.close();
}
}
catch (SQLExcetpion e)
{
log.error("An error occurred closing result set.", e);
}
}
}
And your client code will be something like:
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try
{
connection = getConnection();
statement = connection.prepareStatement(...);
resultSet = statement.executeQuery();
...
}
finally
{
SQLUtils.closeQuietly(resultSet);
SQLUtils.closeQuietly(statment);
SQLUtils.closeQuietly(connection);
}
Update: since Java 7, the various JDBC interfaces extend java.lang.AutoCloseable
and while the above code answers the original question, if you're writing code directly against the JDBC API, it can now be structured:
try (
Connection connection = getConnection();
PreparedStatement statement = connection.prepareStatement(...);
ResultSet resultSet = statement.executeQuery()
)
{
...
}
回答2:
As others have mentioned, a static closeQuietly
utility is the way to go. One thing to add - if you are in the world of java.io
rather than java.sql
then there is a useful interface for exactly this purpose - java.io.Closeable
All the data sources and sinks in java.io
implement this interface - all streams, channels, writers and readers. That way you can create a single utility to cope with the same "exception on close()" issue without requiring many overloaded versions.
e.g.
public class IoUtils {
public static closeQuietly (Closeable closeable) {
try {
closeable.close();
} catch (IOException logAndContinue) {
...
}
}
}
回答3:
I usually did it this way:
try {
try {
..
stmts
...
}
finally {
connection.close():
}
} catch (Exception ex) {
..
stmts
..
}
I usually only used this when I wasn't using a library that took care of this plumbing for me.
As Imagist points out, this isn't technically the same as the finally will run before the catch but I think it solves the problem you were trying to solve.
回答4:
Commons-io also has closeQuietly() for in and output streams. I'm using it all the time. It makes your code much more readable.
回答5:
In Java 10 you can write:
public void java10() throws SQLException {
try (var connection = Connections.openConnection();
var callableStatement = connection.prepareCall("my_call");
var resultSet = callableStatement.executeQuery()) {
while (resultSet.next()) {
var value = resultSet.getString(1);
System.out.println(value);
}
}
}
In Java 7, 8 and 9 you can write:
public void java7() throws SQLException {
try (Connection connection = Connections.openConnection();
CallableStatement callableStatement = connection.prepareCall("my_call");
ResultSet resultSet = callableStatement.executeQuery()) {
while (resultSet.next()) {
String value = resultSet.getString(1);
System.out.println(value);
}
}
}
In Java 6 you need to write all these lines:
public void java6() throws SQLException {
Connection connection = Connections.openConnection();
try {
CallableStatement callableStatement = connection.prepareCall("my_call");
try {
ResultSet resultSet = callableStatement.executeQuery();
try {
while (resultSet.next()) {
String value = resultSet.getString(1);
System.out.println(value);
}
} finally {
try {
resultSet.close();
} catch (Exception ignored) {
}
}
} finally {
try {
callableStatement.close();
} catch (Exception ignored) {
}
}
} finally {
try {
connection.close();
} catch (Exception ignored) {
}
}
}
回答6:
Don't hesitate use one more try ... catch inside finally.
回答7:
Generally you don't want to do anything more than log an exception which happens when closing a resource, so it should really go in its own try/catch. However, this is generic code that will happen often, so Don't Repeat Yourself, and put the close in a static method (as Nick Holt suggests) that way you won't have the two try/catch items in the same method, making the code easier to read and follow.
回答8:
There is also handy Closeables#closeQuitely method in Google Guava library - it can be used for any Closeable
回答9:
Can we have try block followed by finally bock and catch block later to that?
回答10:
just remember .. finally always get execute either with try or catch ..
来源:https://stackoverflow.com/questions/1335812/try-catch-finally-and-then-again-a-try-catch