マスタに依存「するような」「しないような」トランザクション!条件付き外部キー制約

今回は、説明しにくいなぁ。でも図とか面倒なので、文字のみで失礼しますヨ。

欲しい機能

「議事録管理システム」としましょうや。

会議やミーティングの出来事を記録しようと言うモノとしましょうね。この「会議トランザクション」の情報には、シンプルに「議事内容」と「参加者」くらいの項目で考えてくださいな。で、「議事内容」はその都度のデータとして、「参加者」のデータは、どうでも良い一見(イチゲン)さんも参加しますが、ウチの社員(「社員マスタ」{シンプルに「社員ID」と「名前」くらいの項目で考えてくださいね}で管理されている)が参加している。ので、これをリンクさせる・・・って、っま、フツーの設計ですよね。

実装では、「会議トランザクション」に「参加者ID」と「参加者名」の項目を作って、社員マスタからの引用であれば「参加者ID」には「社員ID」がセットされ、ドーデモ良いイチゲンさんの場合は「参加者ID」に「0」とか「99999」とか・・・をセットする。(管理対象外:いわゆる雑コード扱いですね)

こうしておけば、社員さんが事情で名前が変わっても、「その会議のときの名前(トランザクションデータ)」と「現在の名前(マスタデータ)」が、ちゃんと表現できるし、「社員ID」で「会議トランザクション」を抽出すれば、彼・彼女の参加した会議の一覧がgetできて、しっかりと管理対象じゃないですか。

ここまで、イイよね。

で、運用を考えると、当然のことながら、社員登録したけどヘボこいて、削除する・・・って、良く、あるよね(^-^);。だけど一度でもトランザクションデータに引用されている場合は、削除されちゃ困る。・・・そうそう、事情で名前や性別が変わっても良いけど、削除されちゃうと整合性が取れないモノね。

そんなときには、ソースコードにゴリゴリ記述していたら、何か処理を増やすたびに「ヒヤヒヤ」ものですよね。だから、こんなコトはご存知のようにRDBS側で「外部キー」の設定をしておいて、依存関係にキズを付けるような「行為(削除)」があったら、エラー(例外)を出してやる・・・ってすれば、良いワケだ。

で、問題

でも、一方のイチゲンさんの「参加者ID」は、「社員マスタ」には居ないので、トランザクションに登録できないジャン!!!!!

対処

こりゃ困った。でもヨク・ヨク・ヨークpostgresql のdocument(create table あたり)を調べると、nullだけは特例で外部キーの制約対象から外れるみたいです。(パラメータにもよるケドね)

実際に試してみたら、思い通りの結果で「ヤッタぜ、ベイビー」。int8の項目にnullを入れて問題解決!

で、次の問題

ちょっと心配は、O/Rマッピングが上手く行くのか?なんせlong(プリミティブ型)で待っているクラスに、nullをぶつけるのだから・・・ねぇ。ほら、やっぱりエラーじゃんか!

解決案を探す

外部キー制約で、特定の値を除く・・・とかあれば、そこに「0」やら「9999」を設定して・・・、結構調べたが、そんなモノはないようでした。では、Hibernate側で、ゼロだったらnullに変換とか・・・そんな都合の良いのはないようでした。

・・・で、諦めかけて、カッコ悪いけど、ダミーのマスタデータ「社員ID:ゼロ」を入れるしかないのか!ああああ・・・・そんな「逃げ作業」は嫌いじゃ・・・。・・・と、苦しんでいたトコロ、天使のように微笑みかけてくれるサイトを発見しました。

結論

そうなんです。先入観はイカンです。プリミティブ型の項目に「null」はイカンでしょ。だからラッパークラス(java.lang.Long)を使えば、「null」なんて当然あり得るじゃんか!本当に目からウロコでした。特定の数値や文字列でマスタへの依存を表現しようと言う発想も、考えてみれば「姑息」な、昔風な「逃げテクニック」なのカモですね。だって「null」はズバリ・「空っぽ」「無いよ」、じゃないですか!・・・・いたく納得でした。

  1. No comments yet.