February 09, 2004
O/Rマッピング
>O/Rマッピングの議論の中で出てくるのが、RDBMSなんて本当はいらん!って話です。
>でも、何かそれって良く見ると、単にSQLが嫌いなだけのようにも見えるんです。気のせいですか?
元々は、DBのテーブルをJavaのクラスにマッピングしちゃって、SQLを自動生成しましょう!というのを作ろう!と言ってる議論のハナシだと予想していますが、僕はあくまで部外者ですが・・・
はーい。僕は、SQL書くの嫌いな人です!!!!と思わず、手を挙げたくなったりしました(笑)
この発想って、WebObjectsとか、最近だとADO.NETあたりから来てるんだと思いますが(Jakartaにもありますよね?あの辺、名前覚えられん。)、実は、僕も初めてJ2EEを始めたときに、オブジェクト指向~いいねぇ~と、まずやったのが、いわゆるO/Rマッピング(一般的にそう言うんですか?)・・・のクラスを作ることでした。基本的に「セマンティックな構文を作るためのソースコードを、人間様の手で書くのはめんどくさい」人で、実際に、作るときに「SQL書くの嫌いなもんで~」という言い訳として始めた仕組みだったので、ことのほか反応してしまいました。
僕の場合、発想は極めてシンプルで、SQLを作るためのソースコードって冗長だし、「’」とか「、」のつけ忘れをデバッグするのが嫌いだったから自動化したという低レベルな発想だったりします。沢山カラムがあるInsert文のデバッグで、あれーどんなSQL文になったのかなぁ?って、秀丸にコピーして改行入れるとかが、すごく嫌だったもので。
自動化するわけですから、ある程度DBの自由度を奪うのは致し方ないですが、自分ところのは複雑なデータ構造はViewで吸収するいう現状ですね。単純にテーブルを単一のBeanで囲いこむだけでは、きっと物足りないと思います。
経験的にたどり着いたのは、テーブルの構造とJavaのクラスは必ずしも1:1にならず、データを引っ張ってくる時と、DBに書き込む時では使うBeanが変わっていたりします。当然、SELECTするときはViewのクラスで、保存するときは個々のテーブルにマッピングされたクラスです。特に一覧画面を作るときに、無駄なDBへのアクセスを減らすという意味では、仕方ないことであります。
~~~この辺は、このエントリに興味持っていただける方々には釈迦に説法なんだろうなぁとは思いますが、気にしても仕方ないので、続けまーす。
クラス構造は、あまり深追いすると小難しくなる割に自由度がなくなるので、Where句の後ろは、足したければ自由に足せるようになっているぐらいのシンプルな構造にしてます。
これ、SQLインジェクション対策としては品質管理的にテストだけじゃなくて目視検査が必須だったりと、微妙に不満ではありますが、副問い合わせをしなくちゃいけないときに、このクラスが使えないというのだけは避けたかったし、そこまでの構造を考えてる時間がなかったので。
ソースコード検査は、Eclipseで該当メソッド検索して、Where句に放り込む値は、SQL用のエンコードメソッド通さないとダメよ~んとルール決めしておけば、チェックするのは、そんなに大変ではありません。
*SQLインジェクションとは、ログイン認証のIDやパスワードのフィールドに、SQL文として騙すことができる文字を入力することで、認証処理をごまかしてログインしたり、DBのデータを書き換えてしまえるハッキング技。適切な文字列チェックや変換をしていないことで発生する人的不具合。
基本的なフレームワークの発想は、8割楽して、2割はマニュアル化しておいて自由度を残し構造をシンプルに・・・という感じでしょうか。多分、Jakartaなど、みんなで作るプロダクトというのは、とにかくフレームワークとして完成させるために、複雑になったり制約をつけざるを得ない部分もあるんでしょうかね。あくまで想像ですが。
でもSQLは自由度高いので、SQLの野望を完全に汲み取るとJava側が不幸にならざるを得ないんじゃないでしょうかね?確かに、そりゃまぁJava側の都合で富豪的プログラミングにならざるを得ない部分もあって、チャキチャキのDBエンジニアには我慢ならないところもあるだろうなぁとは認識はしています。
その他、コネクションを閉じ忘れられたときに、最悪の事態にならないように、安全に開放されるようにフレームワーク化してもらいました。コネクションのクローズがありやなしやというのはチェックするのは大変なのでありがたいことです。
ーーーーー
JavaとDBの境界線ですが、例えばSELECTタグの選択候補に出すような定数的なマスタデータってDBに持たせますか?
マスタデータがDBに必要であるなら仕方ないですが、僕は、こんなヘリクツを考えていたりします。
・マスタデータによる入力値の制約がJavaクラスの設計で保証されてるなら、DBでリレーションを張る必要はないのでは?
・最終的にマスタデータを使うのがJSPなどでのプレゼン層に限られるなら、一々DBから値を引っ張ってくる処理が無駄では?動的に変更可能な定数をXMLとかリソースファイルで持って、それをJavaレイヤーで扱う方が楽だし、データベース接続のコストがかからず経済的では?
などという観点から、定数クラスにマスタデータを持つのですが、データベースに慣れている人からは割と驚かれてしまいます。つまり、データ設計をデータベースの範囲でのみを考えて設計すると、この辺の考え方は意味不明なわけです。Javaクラスと両方同時に設計すると、こうなるのが自然じゃないかな?と思うわけですね。
つまりJavaというプログラム言語が、クラス構造により、ある一定の制約を作れるのなら、データベースのレイヤーまでその制限を持っていく必要はなく、「ハイパワーなデータストア手段」としてデータベースを扱いたくなる気持ちはわかります。もちろん最終的には適材適所になるのですが、いずれにせよ、DBとJavaはできるだけ疎結合にしたい!そのためにSQL文は極力外側のクラスに追いやるのがベターではないでしょうか?と。
実際、元の議論を見てないので勝手に展開してますが、ホント、単純に「SQL嫌い」というキーワードだけに反応したエントリということで、まったく他意はありませんので、ご容赦ください。(そういう意味では、丸々レスっぽくなってしまってるのに、トラックバックがつけられないのが申し訳ないです。)
でも、その次は、XMLのマッピングも同じクラス使ってやりたくなりますよね。そうすれば、Flash Remotingとかなくても楽できるじゃないですか?・・・と。このネタって元々、SOAPがまだVBのツールキットしかなかったときに、ActiveXDLLでXMLのRPCをするために思いついたネタなので、僕としてはそっちの発想の方がネイティブではあるのですが。VBのSOAPツールキットが激しく難しく、むかついて、これなら自分でXMLをハンドリングした方が確実に速いと思って、そのままDBに保存するために考えたネタでして。今なら、XML-RPCで汎用ライブラリと組み合わせて、あちこちにデータ回せますしね。