- PR -

CLOBへの書き込みについて

投稿者投稿内容
hogest
会議室デビュー日: 2004/10/22
投稿数: 8
投稿日時: 2005-07-10 10:38
HTMLページをCLOB型のカラムへ格納したいのですがうまくいきません。

環境は以下のものを利用しています。
OS  WindowsXP pro
java2SDK 1.4.2_08
DB Oracle9i

DBへの更新に、以下のような処理を行っています。

String sql="UPDATE HOGE_TBL SET PAGE = ? WHERE ID = ? AND NAME = ?";
PreparedStatement statement = connection.prepareStatement(sql);

// contentにHTMLページが入っています。
StringReader reader = new StringReader(content);
statement.setCharacterStream(1, reader, content.length);
statement.setString(2, "AAA");
statement.setString(3, "000");
statement.executeUpdate();
connection.commit();

この方法で実行するとページ内容が444文字以内ならうまく更新されるのですが
それを超える文字数になると更新されません。
また、今までPAGEカラムに入っていた値もNULLとなってしまいます。

どなたか原因と解決方法を知っているようでしたら
ご教授ください。
uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2005-07-10 16:11
JDBCドライバは何を使っていますか? この方法は、TYPE2(OCI)ドライバでしかサポートして
いなかったと思いますが。
Gio
ぬし
会議室デビュー日: 2003/11/28
投稿数: 350
お住まい・勤務地: 都内から横浜の間に少量発生中
投稿日時: 2005-07-10 20:12
uk さんも書かれた通りですが、type 4 のドライバだと LOB (CLOB, BLOB) の扱いに Oracle 独自の方法を用いる必要があったと思います。
(Oracle 8i 8.1.6 の知識がベースなので OTN などで最新の情報を調べることをお勧めします)

大雑把ですが、insert の場合は
(1) LOB のカラムに対しては empty_clob や empty_blob といった Oracle SQL 独自関数で空の LOB を作る
(2) insert したばかりの行を select して ResultSet から LOB を取得し、そこに書き込むためのストリームを得る
(3) ストリームに書き込む
(4) ストリームを close して commit する
という手順だったと思います。
(commit とストリーム close の順が逆かもしれません(_ _)
リソースの解放手順としては後に作った方を先に解放するのが自然だと思いますが、今の場合は commit した後にストリーム内容が消費されるため、ストリーム close を後にしないといけなかった記憶がぼんやりと残っています。
なお、古い話なのでドライバによっては改善されているかもしれません。)

update の場合は古い内容の破棄が必要ですが、ストリームの上書きだけで良いのか、それとも別の手順が必要なのかは、私には知識がありません(_ _)
また、LOB と他のカラム、二つの更新を 1 トランザクション内で(アトミックに)実行する必要があることにもご注意ください。
hogest
会議室デビュー日: 2004/10/22
投稿数: 8
投稿日時: 2005-07-11 09:37
ukさん、Gioさん早速のご回答ありがとうございます。

DB関連については初心者ですのでTYPEについて知識がありませんが、
JDBCドライバはOTNのOracle JDBC Driver V9.2.0(JDK1.4)からダウンロードしたものを利用しています。これはTYPE何になるのでしょう?
Gio
ぬし
会議室デビュー日: 2003/11/28
投稿数: 350
お住まい・勤務地: 都内から横浜の間に少量発生中
投稿日時: 2005-07-11 09:49
検索してみたところ Oracle 9i 以降では必要な JAR ファイルが違うらしいので、それを確認するのが確実と思われますが、もう少し簡単な(手抜きとも言う(_ _))方法をば。

JDBC 接続に使っている URL の先頭が jdbc:oracle:oci8 で始まっていれば type 2、
jdbc:oracle:thin であれば type 4 と考えられます。
hogest
会議室デビュー日: 2004/10/22
投稿数: 8
投稿日時: 2005-07-11 09:56
分かりやすいご説明ありがとうございます。

JDBC接続のURLはjdbc:oracle:thinを利用しています。
ということはtype4ということになりますね。
hogest
会議室デビュー日: 2004/10/22
投稿数: 8
投稿日時: 2005-07-11 18:44
Gioさんから教えていただいた方法で無事CLOBへのデータを更新することができました。
UPDATEする前にCLOBのカラムをEMPTY_CLOB()で初期化することで対応できました。

ありがとうございました。
Gio
ぬし
会議室デビュー日: 2003/11/28
投稿数: 350
お住まい・勤務地: 都内から横浜の間に少量発生中
投稿日時: 2005-07-11 23:02
お役に立てて幸いです(^.^)

けれども運用面では注意してください。
テーブルの中のカラムは LOB locator と呼ばれる 4000 バイトの情報が格納されており、その指す先に LOB の実体があります。

LOB を含まないテーブルの場合は highest watermark と呼ばれる情報を監視し、高くなり過ぎた場合は切り下げる必要があります(他にも監視すべきポイントはあります)が、LOB の場合も同様にテーブルスペースの使用状況を監視し、状況によりパラメータをチューニングする必要があると推測されます。

以降の話は Java から離れるので Database Expert 会議室の方がよろしいでしょうか。

# LOB データが DB 内のどこに格納されるかの認識について、私の誤解があるかもしれません。
# お気づきの方はご指摘ください。

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