- PR -

java.sql.connection、コネクションが有効か無効かの判別

1
投稿者投稿内容
ボブ
常連さん
会議室デビュー日: 2007/10/03
投稿数: 44
投稿日時: 2008-06-24 14:09
Java 1.4.2

Connection con = DriverManager.getConnection("");
のように、Connectionを張り、SQL文を発行しています。

またこのプログラムはLifeCycle型のプログラムで、
init() service() destroy()メソッドがあり、
コンテナ起動時にinitメソッドが呼ばれ、コンテナを落とす際にdestroyメソッドが
呼ばれるようになっています。
コネクションは、毎回張りなおさずに、initメソッドで取得し、destroyメソッドで解放しています。
そしてSQL文の発行は、serviceメソッドの中で行っているのですが、DB側で再起動などが発生した際は、コネクションが有効でなく、SQLExceptionが発生しています。
コネクションを張りなおせば、SQLExceptionは発生しなくなります。

そこで、serviceメソッド内で、コネクションが有効かどうか判断し、無効であればコネクションを張りなおす処理を入れたいのですが、良い手段をご存知ないでしょうか?
以下のAPIにある、isClosedを呼び出し、SQLExceptionになればコネクションが無効と判断しようと思ったのですが、SQLExceptionにならないようです。
http://sdc.sun.co.jp/java/docs/j2se/1.4/ja/docs/ja/api/index.html
progman
大ベテラン
会議室デビュー日: 2005/06/08
投稿数: 227
投稿日時: 2008-06-24 14:40

再接続によって回避しなければならない、切断状態をつくって、そこでエラーを発生
させて、Exception情報等でアプリケーションで再接続すべしというわかる方法を調べて
アプリケーションがそういう状況を検出したら、再接続させる。といった方法になるで
しょう。

リンクのAPI説明で、isClosed()は期待された用途には使えないと記述されてますよね。

環境(os,db,jdbcドライバ等)によってはもっといい方法があるかもしれません。
ボブ
常連さん
会議室デビュー日: 2007/10/03
投稿数: 44
投稿日時: 2008-06-24 15:50
progmanさん、アドバイスありがとうございます。

> 再接続によって回避しなければならない、切断状態をつくって、そこでエラーを発生
> させて、Exception情報等でアプリケーションで再接続すべしというわかる方法を調べて
> アプリケーションがそういう状況を検出したら、再接続させる。といった方法になるで
> しょう。
今はクエリ文を発行した時にはじめて、接続が無効だと判明できます。
本来は、ここで再接続しなければならないと判断し、再接続の処理を入れるようにするべきなのかもしれませんが、実はクエリ文を発行するメソッドのところの例外処理にて、
クエリ文が間違っていた場合のエラー値を取得するような処理を入れています。
(例えばカラム名が間違っていたなど)
よって、ここで判別するのは難しく、本来のクエリ文の発行の前に、ダミーのクエリ文を発行してSQLExceptionをキャッチしようかとも考えました。
しかし、ダミーのクエリ文を毎回発行するくらいなら、毎回コネクションを張りなおした方が性能も変わらないのじゃないかと迷っています。
悩みところです。

環境:Windows server 2003
DBは外だしの設定情報により異なるDBが指定可能
SQLServer2000以降、Oracle9i以降、
上記に対応するJDBCドライバ
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2008-06-24 15:52
Connection#isClosed()は、Connection#close()を、
明示的に呼び出した場合にtrueが帰ってくることが保障されていると書かれていますね。
誰かが明示的に呼び出さずに切断された場合は保証されていないということです。

例えばコネクションプールの実装では、
Ping Queryを定期的に投げる実装が多いかと思います。
例えばOracleが相手なら、select 1 from dual;を投げて、
ダメならば、管理の対象から消すというような感じです。

以上参考までに。
ボブ
常連さん
会議室デビュー日: 2007/10/03
投稿数: 44
投稿日時: 2008-06-24 16:45
引用:

例えばコネクションプールの実装では、
Ping Queryを定期的に投げる実装が多いかと思います。
例えばOracleが相手なら、select 1 from dual;を投げて、
ダメならば、管理の対象から消すというような感じです。

以上参考までに。


かつのりさんありがとうございます。
Oracleの場合なら"select 1 from dual"を投げて反応を見てみればよいのですね。
先が見えてきた気がしました。
SQLServerの場合は調査してみます。
カーニー
ぬし
会議室デビュー日: 2003/09/04
投稿数: 358
お住まい・勤務地: 東京
投稿日時: 2008-06-24 19:01
SQL Serverの場合は
select 1
でいいんじゃないでしょうか。
ボブ
常連さん
会議室デビュー日: 2007/10/03
投稿数: 44
投稿日時: 2008-06-24 19:22
引用:

カーニーさんの書き込み (2008-06-24 19:01) より:
SQL Serverの場合は
select 1
でいいんじゃないでしょうか。


そのようですね!

ちなみに本件のような問題の場合、
コネクションプーリングを使うと解決できるものなんでしょうか?
一般的に皆様はどのような方法で、本件のような問題に対処しているのか気になりました。
1

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