今回は、説明しにくいなぁ。でも図とか面倒なので、文字のみで失礼しますヨ。
欲しい機能
「議事録管理システム」としましょうや。
会議やミーティングの出来事を記録しようと言うモノとしましょうね。この「会議トランザクション」の情報には、シンプルに「議事内容」と「参加者」くらいの項目で考えてくださいな。で、「議事内容」はその都度のデータとして、「参加者」のデータは、どうでも良い一見(イチゲン)さんも参加しますが、ウチの社員(「社員マスタ」{シンプルに「社員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」はズバリ・「空っぽ」「無いよ」、じゃないですか!・・・・いたく納得でした。
● 前オキ
文字列の集合から、特定の文字を検索する際のカユイ点は、文字の厳格性の問題じゃないでしょうか。つまり、「半角(w)・全角(w)」「大文字(A)・小文字(a)」「ひらがな(あ)・カタカナ(ア)」ってのが、普通は別の文字である・・・って、コトです。だから、データには「HANZ」があっても、検索キーワードが「hanz」では、ヒットしてくれない。
これ、何年か前にお得意先の蔵書の管理システムを移植再構築している際に、カユサを感じて対応策を調べていたのです。で、RDBS での関数で強引に差違を吸収してしまうというアイデアを発見し、イタク感激したものです。現在改めて調査したところ、postgresql で文字コードがUTF-8 であればナニヤラおいしいことが出来そうなトピックスがあったのですが、上手く動作しないので、結局上記のテクニックを当初の「英数字のみ」の処理から、「ひらがな・カタカナ」にも対応出きるように、50音を声に出しながら追加したので、忘れないように記録しておきます。
● 具体的な作業
—– postgresql の関数として —– 例えばconv.sqlというファイル名で、以下を作成。
CREATE OR REPLACE FUNCTION conv(text) RETURNS text AS $$
SELECT translate(upper($1)
,’abcdefghijklmnopqrstuvwxyzあいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよらりるれろわゐゑをんがぎぐげござじずぜぞだぢづでどばびぶべぼぱぴぷぺぽゃゅょ-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ ‘
,’ABCDEFGHIJKLMNOPQRSTUVWXYZアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヰヱヲンガギグゲゴザジズゼゾダヂヅデドバビブベボパピプペポャュョ-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ ’);
$$ LANGUAGE SQL IMMUTABLE;
———
で、psql 起動して、「\i conv.sql」 で、関数を作成。関数の存在を確認したければ「 \df」で、関数の中身を確認したければ「select prosrc from pg_proc where proname=’conv’;」で、見えます。
で、これを利用したい時の sql文は、こんな感じ。
select * from HogeHoge where conv(name) like conv(“キーワード”);
##########
あ!、この sql文 は、postgresql に依存しているじゃん!ってことはインターフェースから実装するDAOクラスにそのニュアンスを入れておいたほうがイイネ。
HogeHogeDaoByHibernateForPostgresql とかね。
##########
● 課題
斉藤・斎藤・齋藤・・・といった似たような呼称問題だけど、これは読み仮名などを利用すれば実装上で解決できるかな?(ちょいゴマカシ臭いケド)
といっても、結局「かな・漢字」問題は残るケドね。例えば「らーめん・拉麺」といった感じのパターンじゃ!こういったモノを全部やっつけられれば、google のようなカラクリが実装できるのでしょうが、そんなことに「力」(こだわり)を、かけ続けても本末転倒な「感」もあるので、ここら辺で勘弁してヤル。
娘にもらったプリンをお昼に食べたのですが、風と土 4あわせプリンというヤツ。
- 生っぽいクリーム
- プリン1
- プリン2
- カラメル
となっているソウである。
確かにスペシャル感があって、ウマイ。
じゃ、何が引っかかっているのか?>オレ
上から順番に食べるしかないのか?コレ?早くカラメル部分と絡めて食べたい。
で、フっと思いついた。コイツの横積層バージョンを作ったらドウヨ?・・・って、そんな面倒なことは誰しもヤリたくないでしょうケド。このパッケージじゃ、ひっくり返してお皿にも出せやしない。
わかるよ気持ちは。>パッケージデザイナーさん
でも、工業デザインつうか、こういった意匠って、そこまで考えるベキと思うのです。例えば運動着(!)を入れるスポーツバックってあるでしょ。高校の運動部が使っているようなアレ。縦長のデザインを買っちゃうと、出し入れが超困難!同じサイズでも横長であれば、お着替えサンも楽チンでしょ。そういうコトなんですよね、一番底にある「アリガタサ」って。