- PR -

コネクションは必ずクローズ?

投稿者投稿内容
nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2007-12-01 11:56
完璧な例外処理を書こうとするとなかなか難しいところですね。
手前味噌で申し訳ないですが、以前議論したものがあるので参考にしていただけると幸いです。
http://blogs.wankuma.com/nagise/archive/2007/08/06/89056.aspx
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2007-12-02 03:27
繰り返しになりますが、finallyブロックでクローズをしましょう。

close() メソッドで例外が発生するような状況だとネットワーク障害など、もうプログラム内でリカバーできる状況ではありません。
そういう状況に対する対応はプログラムではなく運用手順に反映させるべきでしょう。
tarnwo
ベテラン
会議室デビュー日: 2002/10/25
投稿数: 58
投稿日時: 2007-12-03 12:55
引用:

Orphanさんの書き込み (2007-12-01 05:06) より:
catch( ClassNotFoundException cnfe ) {
  System.out.println( "ClassNotFoundException" );
  while( true ) {
   try {
    if( null != con ) {
     con.close();
     break;
    }
    break;
   }
   catch( SQLException sqle1 ) {
    System.out.println( "SQLException_1" );
   }
  }
}


ClassNotFoundException 発生時点でconnは生成されないので無意味な処理になっています。
whileで回して単一のコネクションに対しcloseというのも冗長な記述です。
ほかの方が言うとおりfinallyで行うほうがすっきりしますね、
Orphan
ベテラン
会議室デビュー日: 2004/02/06
投稿数: 54
投稿日時: 2007-12-04 01:38
クローズが失敗してもwhileで回している間にネットワークが復活してクローズが成功!てなことになるのかはわかりませんが、そんなイメージで書いてみました。

インギさんがおっしゃっているように、close()での例外発生は運用で対応するようにしたほうが良いと思いました。あとfinallyブロックでクローズするようにします。

結局、close()メソッドがExceptionをスローするメソッドである限り、必ずクローズすることはできない(ORACLEサーバー上のリソースは開放されない)ということになるでしょうか?
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2007-12-04 01:56
前にも書きましたが、Connection#close()がスローするのは、
Exceptionではなく、SQLExceptionです。意味が全く違います。

で、
引用:

結局、close()メソッドがExceptionをスローするメソッドである限り、必ずクローズすることはできない(ORACLEサーバー上のリソースは開放されない)ということになるでしょうか?


close()が例外をスローする可能性があるのと、
必ずクローズできないのとは関連性はありません。

仮に例外をスローしない設計になっていても、
close()の直前にネットワーク障害が発生したら失敗しますよね。
さらに、SQLExceptionをスローしなくても、
RuntimeExceptionやErrorのサブクラスがスローされる場合も考えられますよね。

逆に実装では例外をスローしないが、
実装しているインターフェイスのメソッドに、
throws節が記述されているものもあります。
(他のAPIなど)

したがって、close()の確実性と例外の有無は全く関係ないのです。
Orphan
ベテラン
会議室デビュー日: 2004/02/06
投稿数: 54
投稿日時: 2007-12-08 18:48
DriverManager.getConnection( jdbc:oracle:thin:@localhost:1521:ORCL", "scott", "tiger" );

上記の処理単体でみたときSQLExceptionが発生した場合、コネクションのクローズ処理は必要でしょうか?
(SQLExceptionが発生したということはコネクションは取得できていないということでしょうか?)

同様に

stmt = con.createStatement();
でSQLExceptionが発生したときのステートメントのクローズ、

rs = stmt.executeQuery( SQL文 );
でSQLExceptionが発生したときのリザルトセットのクローズ、

こちらもそれぞれクローズ処理は必要でしょうか?

[ メッセージ編集済み 編集者: Orphan 編集日時 2007-12-08 19:15 ]
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2007-12-08 20:44
引用:

DriverManager.getConnection( jdbc:oracle:thin:@localhost:1521:ORCL", "scott", "tiger" );

上記の処理単体でみたときSQLExceptionが発生した場合、コネクションのクローズ処理は必要でしょうか?
(SQLExceptionが発生したということはコネクションは取得できていないということでしょうか?)


そもそもConnectionのインスタンスは取得できないので、
クローズそのものができないでしょう。

引用:

stmt = con.createStatement();
でSQLExceptionが発生したときのステートメントのクローズ、

rs = stmt.executeQuery( SQL文 );
でSQLExceptionが発生したときのリザルトセットのクローズ、


例外の種類やケースバイケースです。

接続が有効な場合も十分に考えられます。

JDK6から、「一時的な問題であり、継続処理や再処理が可能なことを示す例外」
が増えました。SQLExceptionのサブクラスです。
この例外の場合は再実行という手段もありなので、
クローズはしない場合も考えられます。

処理が終わったら、基本的にどんな場合でも、
finally節で、クローズを試みるのがいいと思います。

私の場合は例外を握りつぶすタイプの、
クローズ専用ユーティリティメソッドをよく使います。
で、必ずfinally節で呼び出すようにしています。
raystar
ぬし
会議室デビュー日: 2003/01/16
投稿数: 251
お住まい・勤務地: Tokyo/Japan
投稿日時: 2007-12-08 23:36
スマートにfinallyでまとめてはいかがですか?
仮にNullPointerExceptionが発生したら、con.close()はとおらないですよね?
while(true) break も意味不明です。
必要ありません。

以下のような感じで、、、、

コード:

public static void main(String[] args) throws SQLException {
 Connection con = null;
 
 try {
  Class.forName( "oracle.jdbc.driver.OracleDriver" );
  con = DriverManager.getConnection( jdbc:oracle:thin:@localhost:1521:ORCL", "scott", "tiger" );
  
 } catch(Exception e) {
  e.printStackTrace();
  throw e;
 
 } finally {
  
  if(con != null) {
con.close();
  }
  
 }
}



どちらがスマートに見えて、メンテしやすそうですか?
ちなみにDBの接続切断等でスローされるSQLExcetionは
アプリでの対応方法はほぼありません。

ResultSet, Statement, PreparedStatement のクローズは
コネクションのクローズより重要です。

OracleではConnectionオブジェクトは V$SESSIONに対応します。
ResultSet は V$OPEN_CURSORS に対応します。

ResultSetをクローズしない場合は、 MAX_CURSORエラーになります。

ご参考に。

[ メッセージ編集済み 編集者: raystar 編集日時 2007-12-08 23:40 ]

スキルアップ/キャリアアップ(JOB@IT)