きどたかのブログ

いつか誰かがこのブログからトラブルを解決しますように。

SQLJに関する所感

人と違ったものを使うと余計な壁にぶちあたるものです。
最近SQLJを触っているので試行錯誤を書いてみます。


SQLJで開発するとき、sqlj.zipやdb2jcc.jarが必要になるでしょう。
JDBC4.0対応のものは、sqlj4.zip、db2jcc4.jarでしょう。
ただ、DB2 ExpressC v9.5にはsqlj4.zipは付いてなかったと思います。
db2jcc4.jarは付いてました。
これは疑問です。なんでsqlj4.zipがないんだっけ?


何かしらの問題で、sqljファイルが赤くコンパイルエラーを出したら、
まずは、sqlj.zipとdb2jcc.jarを疑いなさい。
誰かがWASのfixを当てたら直るはずだという理解に苦しむことを言ってましたが、
sqljはWASが提供してる機能ではないので、そんな事を信じて止まない人には「めっ!」が必要です。
RADのfixを当てることは意味があります。
SDPSahredのpluginsの中に、sqlj.zipやらdb2jcc.jarなんかがあるからです。
ただ、ビルドパスは自分で通しなさい。
残念なことにRADのpluginsにはsqlj4.zipもdb2jcc4.jarもありませんでした。
RADはJDBC3.0しか許さないつもりか!?
JDBC4.0を使いたいなら、本物のDB2からjarを取ってくるざまーす。
そこまでRADに期待しちゃダメ、自分でやれることをやろう。
(ただ、JDK6対応なIDEとして、JDBC4.0対応されたsqlj4.zipやdb2jcc4.jarがいないのは変だから、
IBMさんに言っておいた方が良いのかも知れませんね。)


sqlj.zipは、sqljファイルからjavaファイルを作る(トランスレート)のに使われてるはずです。
また、serファイルなんかも作るのでしょう。
生成されたjavaファイルは、sqlj.runtimeパッケージを使用しているはずで、
それらのクラスは、db2jcc.jarやdb2jcc4.jarの中に同梱されているはずです。



カスタマイズやバインドという作業があります。
カスタマイズとはserファイルを更新することだと思います。
serファイルとは、実行計画みたいな情報が詰まってるのでしょうが、
serファイルが出来た時点ではまだ実際のテーブルにはアクセスしてないので、
たぶん全部が一律フルスキャンな実行計画なんじゃないの?
だってそうでしょ、プライマリーキーが何かすら分かってるはずがないのだもの。
カスタマイズ=バインドではありません。
カスタマイザーが、カスタイマイズ後、自動でバインド作業を始めるのです。
バインドはserファイルを元にDB2へパッケージのバインドをすることのようです。
パッケージのバインドが何をやってるのか知りませんが、
とりあえずDB2の実行計画を固定しているのでしょう。
カスタマイザーをかけることでserが更新されている可能性を考えるならば、
EARを作成しきった後に、とあるJavaプロジェクトでカスタマイズをすることは阿呆のする事でしょう。
(後述のタイムスタンプの件が関係する)


serファイルは、実行時にdb2jcc.jarやdb2jcc4.jarのSQLJランタイムから使用されます。
これは、きっとSQLJのJavaファイルから、
serファイルの名前がSQLJランタイムに渡されてパスが解決されます。
そういう意味で、serファイルはクラスパス上にいないといけません。


よく分かりませんが、バインドした時に確認された何かしらのタイムスタンプが、
実行時にチェックされているようで、エラーでこけることがあります。
おそらくはserファイルにはタイムスタンプが打たれているでしょう。
そのような関連もあってsqljを含むJavaプロジェクトはどのように管理した方が良いのか非常に難しいと感じます。
まず可能な限り一般的なJavaとは切り離したい欲求が増えます。
なぜなら自動ビルドで毎回コンパイルされてしまうと、
serのタイムスタンプが変更され、カスタマイズおよびバインドを度々する必要に迫られるはずだからです。
実行計画を固定するのは良いのですが、他の変更箇所に影響を受けて、
本来必要無いカスタマイズおよびバインドというまで作業が発生しそうで怖いのです。
また、sqljから作られたjavaファイルと、serファイルを私なら同一のJarファイルに配置しません。
それはjavaファイルがチューニングポイントではないからです。



そういえば、WebSphereへアプリケーションをデプロイした後に、SQLJのバインドの作業が出来ます。
私はこの方法をあまり採用したいとは考えていません。
どのようなサイクルでイテレーションするかにもよりますが、基本的にこの作業は非効率です。
性能を意識しないレベルの機能結合においては省略すべきとも言えますが、
バインドしないと動いてたのに、バインドしてからだと動かないような事もあるみたいです。
なんだかやむを得ずバインドして早期に発見しようと試みるんですが、
SQLJ系の間違いに気付くのがあまりにも末期なのが痛いのです。
(どう結論付けたいのか自分でもしっくりきてないが、)
デプロイより前にantを組んでバインドを自動化しとかないとダメでしょう。


あと、性能を意識する段階になった時、どのような単位に変更が加わってデプロイされるべきか?
基本的にserファイル以外は変更がないはずなので、私はserファイルのみのJarがあればいいんじゃないかと考えてます。
仮にSQLJからトランスレートされたJavaファイルまで作り直していると、
.classファイルが違うので、へんちくりんなリンケージエラーみたいなのが出ないか少々怖いです。



そんなこんなでSQLJはリポジトリ管理およびantで工夫が必要になると考えます。


sqljファイルは、非常に開発効率が悪いです。
ある記事によると、簡潔になってハッピーになれる雰囲気で書いてますが、
さまざまなコード補完機能が使えなくて著しくハマります。
Ctrl+Spaceが使えないのがかなりの大打撃です。
ある記事によると、単純なINSERT文の例が出てるのですが、
一般的なJavaではpstmt#setString(hoge)的なコードを書いてありますが、
SQLJの例では、VALUES句に渡されてるホスト変数がどこにあるんだよ的な殺意を抱きました。
一行で書けてます的な態度を取られているのが不快です。
SELECT文は確かにすっきりする可能性があります。
あと、ピンク色の箇所の「:変数」は、Javaの変数として認識されてないので、
カスタマイズおよびバインドの時に書き間違いに気付くことがあるでしょう。
もしもその作業をしてなかったら、実行時にいきなりこけます。
そして見たことも無い例外に慌てふためく人々が現れるのです。


そんなこんなで、RADさんはもうちょっとSQLJプラグインを強化してくれないと開発者が苦労する。


JPAをどんどん使っていこうとしてる人々が増える中、
なんでオイラはこんなSQLJなんか触ってるんじゃろ。


sqljは、レイヤー的にはDBに寄りすぎてます。
きっとそのせいもあって、
sqljを動かすことが出来るオープンなフレームワークはまだ見たことがありません。
仮にそんなフレームワークがあったとしても、
世の中の99%はそれに興味を示さない気がします。
JPAのO/RマッパーがSQLJサポートをしていたら気にするんだけど、
たぶんそんなO/Rマッパーいないんじゃないの?
たとえばOracleTopLinkでSQLJ対応してたら面白いんだけどねー。