私はしばしば次のような状況に遭遇しました:-
try{
...
stmts
...
}
catch(Exception ex) {
...
stmts
...
} finally {
connection.close // throws an exception
}
これにはまだ try - catch ブロックが最後に必要です。
これを克服するためのベストプラクティスは何ですか?
私はしばしば次のような状況に遭遇しました:-
try{
...
stmts
...
}
catch(Exception ex) {
...
stmts
...
} finally {
connection.close // throws an exception
}
これにはまだ try - catch ブロックが最後に必要です。
これを克服するためのベストプラクティスは何ですか?
このような例外をキャッチしてログに記録するメソッドをSQLUtils
含むクラスを作成し、必要に応じて使用します。static closeQuietly
最終的には次のようになります。
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);
}
}
}
そして、クライアントコードは次のようになります。
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);
}
更新: Java 7以降、さまざまなJDBCインターフェースが拡張java.lang.AutoCloseable
され、上記のコードは元の質問に答えますが、JDBC APIに対して直接コードを記述している場合は、次のように構造化できます。
try (
Connection connection = getConnection();
PreparedStatement statement = connection.prepareStatement(...);
ResultSet resultSet = statement.executeQuery()
)
{
...
}
他の人が述べたように、静的closeQuietly
ユーティリティが最適です。追加することの1つ-あなたが世界にいるのではjava.io
なくjava.sql
、まさにこの目的のための便利なインターフェースがあります-java.io.Closeable
のすべてのデータ ソースとシンク (java.io
すべてのストリーム、チャネル、ライター、およびリーダー) は、このインターフェイスを実装します。そうすれば、多くのオーバーロードされたバージョンを必要とせずに、同じ「close() の例外」問題に対処する単一のユーティリティを作成できます。
例えば
public class IoUtils {
public static closeQuietly (Closeable closeable) {
try {
closeable.close();
} catch (IOException logAndContinue) {
...
}
}
}
私は通常、このようにしました:
try {
try {
..
stmts
...
}
finally {
connection.close():
}
} catch (Exception ex) {
..
stmts
..
}
私は通常、この配管を処理してくれるライブラリを使用していないときにのみこれを使用しました。
Imagistが指摘しているように、これは技術的には finally が catch の前に実行されるのと同じではありませんが、解決しようとしていた問題は解決すると思います。
Commons-io には、入力および出力ストリーム用の closeQuietly() もあります。いつも使っています。これにより、コードがはるかに読みやすくなります。
Java 10 では、次のように記述できます。
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);
}
}
}
Java 7、8、および 9 では、次のように記述できます。
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);
}
}
}
Java 6 では、次のすべての行を記述する必要があります。
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) {
}
}
}
もう一度試してみることを躊躇しないでください...最後に中に入ってください。
通常、リソースを閉じるときに発生する例外をログに記録する以上のことはしたくないので、実際には独自の try/catch に入れる必要があります。ただし、これは頻繁に発生する一般的なコードであるため、自分自身を繰り返さないでください。2 つの try/catch 項目が同じメソッドに含まれないように、(Nick Holt が示唆するように) 静的メソッドに close を配置してください。コードを読みやすく、追跡しやすくします。
Google Guava ライブラリには便利な Closeables#closeQuitely メソッドもあります - これは任意の Closeable に使用できます
try ブロックに続いて finally ブロックを実行し、その後で catch ブロックを実行することはできますか?
覚えておいてください..最終的には常にtryまたはcatchのいずれかで実行されます..