Javaに関する様々な情報をご紹介します。

Javaに関する様々な情報をご紹介します。
評価

0

JDK1.6でDBからBLOB型のデータを取得したい!(再質問)

少し前に、「OracleでBLOB型の項目にデータを登録したい。」の質問をしたものです。

あまりに色々試しすぎて自分でもよくわからなくなってきてしまったため、一度自分の中で整理も含め、改めて質問をさせてもらいました。 

状況としましては、この度JDK1.4からJDK6にバージョンを上げましたところ、BLOB型のデータをSQLより取得している部分が一部コンパイルエラーとなってしまい悩んでいます。

環境
apache2、tomcat6、JDK6、oracle9、JDBCドライバ(commons-dbcp-1.2.1.jar)を使用。 

エラー箇所
SQL文を実行し、resultSetよりBLOB型のデータを取り出す部分
((OracleResultSet)((DelegatingResultSet)resultSet).getDelegate()).getBLOB("AM")

JDK1.4では使用できた、oracle.jdbc.driver.OracleResultSetが使えなくなったためコンパイルエラーが起きています。

JDK6の場合は、どのように取得すればいいのでしょうか。

java.sql.Blobを使用し、(Blob)(resultSet.getBlob("AM"))で普通に取得できるというアドバイスもいただきましたが、
java.lang.AbstractMethodError: oracle.jdbc.driver.OracleResultSetImpl.getBlob(Ljava/lang/String;)Ljava/sql/Blob;
が表示され見つからないと言われてしまいました。

Javadocを調べたところ、JDK6の場合はjava.sql.Blobが使用できるみたいなんですが…
コンパイルも通ってます。

どこが悪いのか…
こういうこと試してみたら?とか、ここ間違っているよという方がいらっしゃいましたら、よろしくお願いします。

20

回答

14313

閲覧

20件の回答

評価

0

すみません。tomcatのバージョンは5でした。

評価

0

自分もあまり詳しくはないのですが、例えばtomcatのバージョンやドライバーが古く対応しきれていない事など考えられませんか?

ちょっと口になりますが、Javaなど新しいバージョンが出るたびに以前出来た事が出来なくなったりするのはやめて欲しいですよね。
eclipseの設定でもバージョンアップ後困った事が多々ありました。

評価

30

>ちょっと口になりますが
どうでも良いが、これは「愚痴」だろうな。

>以前出来た事が出来なくなったり
素直に書いていればそう多くはないはずだが、一体何だろ
う。

Tomcatを5系に上げたときにデフォルトコンストラクタのな
いbeanが使えなくなったり、6系に上げたときにライブラリの
読み込み順が微妙に変わったりは対処した覚えがあるが、
Javaそのものでは何があったかな。

評価

0

OracleResultSetの部分を右クリックして、宣言→ワークスペースと選ぶと、
検索ウィンドウにjarの名前や、どこに格納されているか表示されますか?

以前教えた方法は、実行時のjarの場所を調べる方法で、
コンパイルは出来るのに、実行時にメソッドが無いと言われた時に有用です。

> ((OracleResultSet)((DelegatingResultSet)resultSet).getDelegate()).getBLOB("AM")
たぶん、キャストされたOracleResultSetの場所ではなく、
resultSetのクラスがどのjarに格納されているかを確認しちゃってませんか?

評価

0

すみません。
よく意味がわかりません。

>OracleResultSetの部分を右クリックして、宣言→ワークスペースと選ぶと、
>検索ウィンドウにjarの名前や、どこに格納されているか表示されますか?
OracleResultSetはJDK6にあげたらコンパイルさえ通りませんので、もちろん何も出てきません!

>たぶん、キャストされたOracleResultSetの場所ではなく、
>resultSetのクラスがどのjarに格納されているかを確認しちゃってませんか?
はい!そうです!
resultSetの方ではなくOracleResultSetの方ですね!
名前が似ていたのですみません。
がしかし、OracleResultSetではコンパイルも通らないので、確認できませんよね?

評価

0

ちょっと以前のやりとりを、ゆっくり読み返す時間も取れないので、
変な事言っちゃうかもしれませんが。

OracleのJDBCドライバであるojdbcなんちゃら.jarが、
プロジェクトのプロパティの、ビルドパスに指定されているか、
確認してみてください。


通常、WEB-INF/lib/に入っているjarは、コンパイル時にも実行時にも
Webアプリケーションから参照できます.
(WEB-INF/libの中のjarは、自動でビルドパスに含まれる)

しかし、JDBCドライバは、Webアプリだけではなく、Tomcatが必要としているので、
WEB-INF/libではなく、$CATALINA_HOME/common/lib/の方に入れます。
その場合、自動ではビルドパスに含まれないので、
コンパイルする為には、手動でビルドパスに追加してあげる必要があります。

詳しくは、Tomcatのクラスローダーについて調べてみて下さい。

評価

0

ojdbc.jarが、確かにビルドパスには追加されていませんでした。
ですが、java6に上げる前は、ojdbc.jarをビルドパスに含めなくっても、コンパイル通ってたんですが、これはjava1.4のjarに含まさってたのかな?

で、ojdbc.jarをビルドパスに追加したところ、
stateBean.setAm(((OracleResultSet)((DelegatingResultSet)resultSet).getDelegate()).getBLOB("AM"));
の、OracleResultSetはコンパイル通りました。
DelegatingResultSetは、まだコンパイルエラーです。

評価

0

> ojdbc.jarをビルドパスに含めなくっても、コンパイル通ってたんですが、
> これはjava1.4のjarに含まさってたのかな?

JDBCというのは共通インターフェースですからね。普通は開発時にはドライバを必要としません。これはJDBC APIの範囲に収まっている場合です。

> エラー箇所
> SQL文を実行し、resultSetよりBLOB型のデータを取り出す部分
> ((OracleResultSet)((DelegatingResultSet)resultSet)
> .getDelegate()).getBLOB("AM")

このように OracleResultSet のような実装依存の具象クラス名が出てくると話は別です。実際に OracleResultSet を含むライブラリへの参照が開発時に必要になってしまいます。

以前、問題がなかったというのはJDBCの範囲に収まっていて、Oracle独自のクラス参照がなかったのではないでしょうか。

DelegatingResultSetも同様です。Jakarta DBCPへのライブラリ参照が不足しているのだと思います。

評価

0

>以前、問題がなかったというのはJDBCの範囲に収まっていて、
>Oracle独自のクラス参照がなかったのではないでしょうか。
以前から何もソース変えていないのに、Oracle独自のクラス参照がなかったという事は考えられますか?
本当にただ、jdk6に上げただけなんですが…。

評価

0

ソースを変えていないのであれば、以前はOracle JDBCライブラリへの正しい参照があったということなのでしょう。

たとえば私は良く使うライブラリをJavaのインストールフォルダのlib\extに入れています。ここに入れているライブラリはJava実行環境全体から参照可能になります。(eclipseなどでも参照できるようになります。)

以前のJDKのlib\extにはライブラリを置いていて、JDK6に入れ替えたときにlib\extが初期状態に戻ったとか考えられませんか?

とにかく、参照可能な位置にあったOracle JDBCライブラリが、いまは参照可能な位置に存在していない、ということだと思います。Oracle JDBCはJDKに含まれるライブラリではありませんから、以前もあなたが参照可能な位置に置いたはずなのですが…。

評価

0

>以前のJDKのlib\extにはライブラリを置いていて、JDK6に入れ替えたときにlib\extが
>初期状態に戻ったとか考えられませんか?
現在、私のマシンには、jdk1.4とjdk6両方存在しています。消して入れた訳ではなく、別フォルダで管理してて、eclipseでどちらを動かすか決めています。
もしかして、これがまずいのでしょうかね?

両方のバージョンのJAVA_HOME\libを見てみましたが、extフォルダ自体存在しませんでした。


評価

0

問題解決への直接的な回答ではありませんが、

>現在、私のマシンには、jdk1.4とjdk6両方存在しています
まずくないです。よくあることだと思います。

>JAVA_HOME\libを見てみましたが
見る場所が違います。
extフォルダについて調べてみましたか?

評価

0

1.4環境は、本当に自分でセットアップしたの?
または、自分のやってることを理解しつつセットアップし
た?
既に出ていることだが、Oracle実装クラスが、何もしないで
使えることはありえない。
必ず誰かがそれを入れ、セットアップしたはずなんだ。
今よりさらに分かっていなかった頃に、言われるがままに
(または書いてある通りに)設定したんじゃないかな。


何かOracle固有のことが必要なのでなければ、なるべく標準
JDBCだけで書いた方が良い。
DBMSに縛られないように(というか、そのためのJDBCイン
ターフェイスだし)。

評価

0

javaは確かに自分でインストールしました!
ですが、lib\extにドライバをコピーした記憶がないんですが…このドライバの置く場所ってtomcat\common\libでも大丈夫ですよね?
こっちには、classes12.jar、classes111.jar、ojdbc6.jar、ojdbc14.jarなどがはいっています。


それと、lib\extについては確かに自分はわかっていないので、少し調べつつ自分のフォルダを見て見ました。
すると、前にテストで使用したことのある、postgresのドライバやsqlliteのドライバなどが入っていたんですが、この場合どれがきいているのでしょうかねぇ?

評価

0

>ドライバの置く場所ってtomcat\common\libでも大丈夫ですよね?

JDBCインターフェースを使っているだけなら、実行時に参照できればいいので tomcat\common\lib で OK なはず。でも、今回はJDBCを逸脱して具象クラス名が出てきているので、開発時にも参照できる必要がある。ビルドパスに追加が必要というのはそういうこと。

あと、DelegatingResultSetでもエラーが出ているそうだけど、
commons DBCPのjarライブラリも tomcat\common\lib にコピーして、さらにビルドパスにも追加しないといけないですよ。
 
> 前にテストで使用したことのある、postgresのドライバや
> sqlliteのドライバなどが入っていたんですが、
> この場合どれがきいているのでしょうかねぇ?

ドライバは複数入っていても大丈夫。Class.forName()で使うものだけロードできるし、実際に使われるのはJDBC接続文字列で記述されたもの。JDBC 4.0以降だったかな… Class.forName()で明示的にクラスをロードしなくても自動的にロードしてくれるようにもなったと記憶しています。とにかく、PostgreSQLやSQLiteのドライバが存在することは気にしなくて大丈夫。

評価

0

なるほど!
物凄くわかりやすい説明ありがとうございます。
DBCPのjarビルドパスに追加したらコンパイル通りました!
具象クラス名…この辺が自分はまだわからないので、もう少し勉強してみます!

結果、java6に変更したからこの部分のコンパイルが通らなくなった訳ではないという事ですね?
java4の時はどうして通ってたか不思議だけど…。

ですが、java.lang.AbstractMethodError: oracle.jdbc.driver.OracleResultSetImpl.getBlob(Ljava/lang/String;)Ljava/sql/Blob;
と出るので、やはりこの書き方ではjava6ではダメと言う事ですねぇ。

あっ!本題を説明すると、java6にあげてからoracleへのBLOB型の登録、取得表示ができなくなってしまったのです。そこで、この質問への流れになりました。

また、別スレたてさせていただきます。
有難うございました。

評価

0

AbstractMethodError

アプリケーションが abstract メソッドを呼び出そうとした場合にスローされます。通常、このエラーはコンパイラによって検出されます。 現在実行中のメソッドを最後にコンパイルしたあとで、あるクラスの定義が変更されて互換性が失われた場合にだけ、実行時にこのエラーが発生します。

ですって。(私は遭遇したことないエラーです。)

最近はTomcat使わないから良く分からないけど、ホットデプロイで問題が起こっていたりしませんかね。Tomcatをコールドスタートさせれば改善するかもしれない…。

うまくいかなかったら、PC自体を再起動して、ビルドして、ビルドエラーがなくなったことを確認してから、Tomcatを起動する、この手順でどうでしょうか。

評価

0

追加。もうひとつ、ビルド時のJDBCバージョンと、実行時のJDBCバージョンが異なる、つまりインターフェースと実装クラスの不一致なんかでも発生するのかもしれません。

評価

0

JDBCのバージョンを1.2から1.4に変更してみました。

すると、java.lang.ClassCastException: org.apache.commons.dbcp.DelegatingResultSet 
に変わりました!

評価

0

調べるって作業したくないんだろうなこのひと

質問から6ヶ月以上経過しているので、回答を書き込むことはできません。