- PR -

Oracle+jspで、ORA-01000: 最大オープン・カーソル数を超えました。

1
投稿者投稿内容
Dr.Doraemon
ぬし
会議室デビュー日: 2002/03/23
投稿数: 265
投稿日時: 2003-12-17 15:58
いつもお世話になっております。

現在、サーブレット+jspで、Oracleからデータを引っ張るプログラムを作っているのですが件名のとおり、「ORA-01000: 最大オープン・カーソル数を超えました。」というメッセージが表示されてしまいます。

 コネクションプールのソースを参考にして、プールから持ってきたものを使いまわす形になっているので、いくつものSQLがひとつのカーソルの中で行われれているという扱いになってしまっているようなのですが、果たしてその見解でいいかもよくわかりません。
 この場合は、やはりプールを利用するのではなく、他の方法に頼ったほうがよいのでしょうか?もし、なにか回避策や解決へのヒントがありましたら、是非教えていただきたいのです。

環境は、下記のとおりです。
WindowsXP Pro SP1
Oracle 8.1.6
Tomcat 4.0.6(Jbuilder 9内)
j2sdk 1.4

よろしくお願いいたします。
ぽん
大ベテラン
会議室デビュー日: 2003/05/13
投稿数: 157
投稿日時: 2003-12-17 16:03
Statement#close()してますか?
Dr.Doraemon
ぬし
会議室デビュー日: 2002/03/23
投稿数: 265
投稿日時: 2003-12-17 16:26
ぽんさん、早々のレスありがとうございます。

 参考にしたソースのところに、(http://www.atmarkit.co.jp/fjava/rensai/jsp2_04/jsp2_04_3.html)「statement.close();」(ソース33行目)が書いてあるのですが、実際に、動かすと、ResultSetを受け取ったところでwhile(next)でまわそうとすると「java.sql.SQLException: クローズされた文です。: next」と表示されてしまいます。なので、「statement.close();」をはずしました。

たしかに、原因はここっぽいですね。

ただ、参考のまますると、nextが呼べないのですが、これは、こちらのコーディングミスになるのでしょうか?それともなにか回避方を探さなければいけないのでしょうか?

なにか、アドバイスをいただけますでしょうか?
よろしくお願いいたします。
ぽん
大ベテラン
会議室デビュー日: 2003/05/13
投稿数: 157
投稿日時: 2003-12-17 16:51
例文が良くないですね...
他のサンプルを探した方が良いと思います。
(これ書いた人、テストしたのかな・・・)

※今時間が無いので、また後でちゃんと書きます。

[追記]
サンプルが見つからなければ、
「コネクションプールの仕方」とでもいうスレッドを立ち上げても良いかもしれませんね。

[ メッセージ編集済み 編集者: ぽん 編集日時 2003-12-17 17:17 ]
Dr.Doraemon
ぬし
会議室デビュー日: 2002/03/23
投稿数: 265
投稿日時: 2003-12-17 17:23
ぽん様、重ね々ありがとうございます。

 サンプルのソースで、ResultSetを返す部分を、クラスをつくり、そこのメンバー変数に「ResultSet」と「Statement」の2つをもったクラスの方で戻すようにして、そのクラスの呼び先で、Statementをclose()するようにしました。

 すると、今テスト中なのですが、今のところ、オープンカーソル数を超えたというメッセージは出なくなりました。たぶん、これでなんとかなると思います。

解決へのヒントをいただきましてありがとうございました。
ぽん
大ベテラン
会議室デビュー日: 2003/05/13
投稿数: 157
投稿日時: 2003-12-17 19:30
時間が出来ました

既に解決されている様ですが、参考までに。

なるべくサンプルを変えないようにするなら、こんな感じでしょうか。
(getResultSet()の変わりに)
コード:
public void process(String sql,Processable processable) throws Exception {
	getConnection();
	try {
		Statement statement = connection.createStatement();
		ResultSet resultSet = statement.executeQuery(sql);

		processable.process(resultSet);

		resultSet.close();
		statement.close();
	}
	catch(Exception e) {
		throw e;
	}
	finally {
		releaseConnection(); 
	}
}

interface Processable {
	void process(ResultSet resultSet) throws SqlException;
}

class SampleProcessable implements Processable {
	public void process(ResultSet resultSet) throws SqlException {
		while (resultSet.next()) {
			//処理
		}
	}
}



他にも解決方法はたくさんあるので、方法の1つと捉えて下さい。
Dr.Doraemon
ぬし
会議室デビュー日: 2002/03/23
投稿数: 265
投稿日時: 2003-12-18 21:01
ぽん様
お世話になっております。

わざわざ、サンプルまでいただきましてありがとうございます。
おかげさまで解決をいたしました。
迅速に対応をしていただきまして、大変感謝しております。
ありがとうございました。

※あのサンプルが間違っているというのは、何とかならないものでしょうかね・・・。
yuk@lavans
会議室デビュー日: 2005/07/26
投稿数: 5
投稿日時: 2007-06-17 20:12
とっくに解決した話で恐縮ですが、サンプルはコネクションプール自作の話で、
Statement#close()を呼んでもなにもしないように実装してあると
明記してありますね。だからあのサンプルにすべて従えば動くはずです。

だからといってResultSetを返すようなメソッドはやめるべきだと思いますが。
マルチスレッドで動かしたときに、すでにreleaseConnection()されたものが
再利用されてしまうとアウトですね。
1

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