とあるツールを作ろうとしてクラス図を描いたはいいが、継承の親子関係にあるクラスそれぞれをテーブルに結びつけるってできるのか? と疑問に思った。
これまでは、現実世界からクラス図に落とし込むときに、テーブルも作りやすいように描いてきたけど、今回はそのクラスの数が今までよりもかなり多くなってきて、ややこしいから、できれば1クラス1テーブルになってくるととてもありがたいわけだ。
幸い、データベースは PostgreSQL なのでテーブルの継承機能がある。
が、今まで実用で使ったことがなかったので、試してみた。
まず、単純に親テーブル(items)と子テーブル(servers)を作る。
んでもって、items テーブルにデータを入れてみる。これは問題ない。
次に、子テーブルの servers にデータを入れてみる。 入れたあとに、items テーブルにもデータが入っていたら期待通りの動作。
できてる。
また、servers をさらに継承した hpcservers を作ってみたが、こちらも問題なかった。
ということで、イケるのは分かった。
ただ、上記のテーブル定義だと、孫テーブルで speed だけ指定しても通ってしまうので、まじめに制約を含めて作り直した。
で、データを入れてから確認してみた。
期待通りの動きですね。
子や孫テーブルの定義(psql 対話インタフェースにて \d servers とか)を見ると、ちゃんと親から引き継いだカラムも含まれているから、CakePHP ではそのまま意識せずに bake しても大丈夫なんじゃないかと思う。
というわけで、安心して設計を進める。
ただ、ER図には継承/汎化を表現する記号がない(と思う)ので、クラス図上でなるべくプロパティを丁寧に書いて、そこから最終的に SQL に落とし込むことになるかな。
これまでは、現実世界からクラス図に落とし込むときに、テーブルも作りやすいように描いてきたけど、今回はそのクラスの数が今までよりもかなり多くなってきて、ややこしいから、できれば1クラス1テーブルになってくるととてもありがたいわけだ。
幸い、データベースは PostgreSQL なのでテーブルの継承機能がある。
が、今まで実用で使ったことがなかったので、試してみた。
まず、単純に親テーブル(items)と子テーブル(servers)を作る。
create table items ( id serial, name varchar(10), primary key(id)); create table servers ( typename varchar(10), primary key(id)); |
んでもって、items テーブルにデータを入れてみる。これは問題ない。
test=# insert into items ( name ) values ('logger'), ('dns'); INSERT 0 2 |
次に、子テーブルの servers にデータを入れてみる。 入れたあとに、items テーブルにもデータが入っていたら期待通りの動作。
test=# insert into servers ( name, typename ) values ('mail', 'RX78'), ('web', 'PC-8001'); INSERT 0 2 test=# select * from servers; id | name | typename ----+------+---------- 4 | mail | RX78 5 | web | PC-8001 (2 rows) test=# select * from items; id | name ----+-------- 2 | logger 3 | dns 4 | mail 5 | web (4 rows) |
できてる。
また、servers をさらに継承した hpcservers を作ってみたが、こちらも問題なかった。
ということで、イケるのは分かった。
ただ、上記のテーブル定義だと、孫テーブルで speed だけ指定しても通ってしまうので、まじめに制約を含めて作り直した。
NOTICE: CREATE TABLE will create implicit sequence "items_id_seq" for serial column "items.id" NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "items_pkey" for table "items" NOTICE: CREATE TABLE / UNIQUE will create implicit index "items_name_key" for table "items" CREATE TABLE test=# create table servers ( typename varchar(10) not null, primary key(id)) inherits (items); NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "servers_pkey" for table "servers" CREATE TABLE test=# create table hpcservers ( speed int ) inherits (servers); CREATE TABLE |
で、データを入れてから確認してみた。
test=# insert into hpcservers ( speed ) values (10); ERROR: null value in column "name" violates not-null constraint test=# insert into hpcservers ( name, speed ) values ('RX78', 10); ERROR: null value in column "typename" violates not-null constraint test=# insert into hpcservers ( name, typename, speed ) values ('logger', 'RX78', 10); INSERT 0 1 test=# select * from hpcservers; id | name | typename | speed ----+--------+----------+------- 3 | logger | RX78 | 10 (1 row) test=# select * from servers; id | name | typename ----+--------+---------- 3 | logger | RX78 (1 row) test=# select * from items; id | name ----+-------- 3 | logger (1 row) |
期待通りの動きですね。
子や孫テーブルの定義(psql 対話インタフェースにて \d servers とか)を見ると、ちゃんと親から引き継いだカラムも含まれているから、CakePHP ではそのまま意識せずに bake しても大丈夫なんじゃないかと思う。
というわけで、安心して設計を進める。
ただ、ER図には継承/汎化を表現する記号がない(と思う)ので、クラス図上でなるべくプロパティを丁寧に書いて、そこから最終的に SQL に落とし込むことになるかな。