きどたかのブログ

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

SQLJについて知っておくこと

SQLJのイメージ。

  • 静的SQL
  • サポートしてるIDEが少ない。きっとRADくらいのものか。
  • IDEのリファクタリングが効かない。
  • コードは少なくなるというが、IDEがしょぼいので生産性は低い。
  • プリコンパイルが遅いのでイラつく
  • customize時にonline-checkが行える。実際のテーブルと突き合わせて、テーブル存在有無、カラム存在有無などを検査できる。
  • z/OS以外の環境では使わない方がいいだろう。sqljEnableClassLoaderSpecificProfilesがDB2 for z/OSでしか使えないプロパティになっているので通常のJ2EEサーバーで動かすには問題があると思われる。


SQLJを採用するなら、静的SQLにしたいか否かのみを判断基準にして、開発コストを積んだ方がいいが、
sqljEnableClassLoaderSpecificProfilesの点は注意が必要だ。


RADの場合、プリコンパイル用に、.projectにbuildCommandsが追加されて処理されている。
eclipse詳しい人なら同じようなものをすぐに作れるのではないだろうか。


ant等でsqljをプリコンパイルしてからじゃないと、javaファイルが出来ないので、
jenkinsを使ったりしている場合はそういうantを書かないといけない。
なお、勝手にSystem.exitしたりするツールがいるので、
db2.jcc.sqljToolsExitJVMOnCompletionをfalseにした方がいい。


.serファイルは、プリコンパイル時にJavaファイルと共に作成される。
この時はJavaの型に関する情報しかない。
customize時に、online-checkがyesなら、DB2側の情報を拾ってくる。


SQLの実行時、.serファイルからコレクションIDおよびパッケージ名を拾ってくる。
それらを元にDB2本体側のパッケージを探して実行するわけだ。
もしSET CURRENT PACKAGESETを使用した場合(データソース・プロパティとかで)、
シリアライズド・プロファイルの中にあるコレクションIDは使用されずに、
SET CURRENT PACKAGESETで指定したコレクションIDが使用される。
z/OSの場合は、pkListとplanNameが使用可能で、pkListの方が推奨されている。
これは従来のPLANを作っても、ぶっちゃけPLANでアクセスしないということを意味するので、
PLAN作るってのはもはやただの無駄作業ということになるであろう。
pkListは「コレクションID.*,コレクションID.*,....」の形式で書くので、
SET CURRENT PACKAGESETでは一つしか指定出来なかったのが複数コレクションID指定出来る。
ここで疑問なのは、これは書いた順のコレクションIDで処理されるのか否かだ。
先頭のコレクションIDで見つからなければ、内部で例外が発生してから、後続のコレクションIDを探すだろう。
SQL投げる度に裏で例外が出てしまうのは頂けない。
Javaエンジニアなら例外生成のコストの高さは知ってるはずだから。


カスタマイズせずに、db2.jcc.sqljUncustomizedWarningOrException=2にしておくと、例外が投げられてくる。


SQLの実行時、.serファイルをクラスパスからを探すことになる。
というわけで、シリアライズド・プロファイルのパスは、Javaソースに埋め込まれている。
プリコンパイル時にJavaソースが1つ生成されるが、そのファイル内には2クラスある。
片方のクラスがプロファイルを探すためのキーとして用いられる。
このキーは、クラスローダーも意識する。
sqljEnableClassLoaderSpecificProfilesがどこかしらで関係してくるはず。


customizeとbindをごっちゃにしている人がいるが、
bindはBIND PACKAGEというDB2側のコマンドであると言っていいだろう。
その際に渡すパラメータが-bindoptionsってことになる。


整合性トークンというものがあり、.serファイルに埋め込まれるし、bind時にDB2側に格納される。
整合性トークンがあるので、リポジトリで何を管理するのかは悩ましい。
整合性トークンが合わなくなると、パッケージが見つからないという例外になる。