- PR -

COMPOSITEパターンのギモンについて

1
投稿者投稿内容
てっく
常連さん
会議室デビュー日: 2002/11/05
投稿数: 28
投稿日時: 2004-01-08 16:44
いつもお世話になっています、てっくと申します。

ふとCOMPOSITEパターンについて疑問を抱いたので、どのたかご教授ください。

例えばOSなどのディレクトリ階層があるとします。
簡単のためにCOMPOSITEパターンのComponentを次のように作成します。
(かなり省略)
【抽象クラスEntry】
abstract class Entry {
public abstract int getSize(); //サイズを取得
public Entry add(Entry obj) throws Exception {
//ファイルの場合は追加できない、ディレクトリの場合は追加可能
throw new Exception();
}
}
続いてLeafを次のように作成します。
【クラスFile】
public class File extends Entry {
private int size; //ファイルサイズ
public int getSize() {return size;}
}
更にCompositeを次のように作成します。
【クラスDirectory】
public class Directory extends Entry {
private LinkedList children = new LinkedList();
public int getSize() {
//配下のディレクトリとファイル全てのサイズの合計を算出
}
public Entry add(Entry obj) {
//省略
}
}

ここまでは良いのですが、これら階層情報をRDBMSに格納する場合、
どのような形で格納するものなのでしょうか?
通常RDBMSのテーブルは例えば次のように定義されていると思います。
(ちょっと適当ですが・・・)
【テーブルEntry】
1:EntryId(主キー)
2:EntryName(ディレクトリ名、もしくはファイル名)
3:FileSize(ファイルの場合はサイズ、ディレクトリの場合はNULL)
4:ParentID(親ディレクトリのID、最上位のみNULL)

この考え方って4のポインタは「親」を指しますよね?
でも先ほどのCOMPOSITEパターンではポインタは「子」を指しますよね?
だからInsertもSelectも、O-Rのマッピングが大変なのでは・・・と。

テーブルEntryの4を「子」を指すように改造すれば、
O-Rのマッピングは簡単になるような気もするのですが、
今度はテーブル容量が増えてしまうような気がします。。。


どなたかご教授願えませんでしょうか?
よろしくお願いします。
uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2004-01-08 17:28
引用:

てっくさんの書き込み (2004-01-08 16:44) より:
通常RDBMSのテーブルは例えば次のように定義されていると思います。
(ちょっと適当ですが・・・)
【テーブルEntry】
1:EntryId(主キー)
2:EntryName(ディレクトリ名、もしくはファイル名)
3:FileSize(ファイルの場合はサイズ、ディレクトリの場合はNULL)
4:ParentID(親ディレクトリのID、最上位のみNULL)


アクセスパターンが示されていないのでなんともいえませんが、一般的にはこの通りだと
思います。

引用:

でも先ほどのCOMPOSITEパターンではポインタは「子」を指しますよね?
だからInsertもSelectも、O-Rのマッピングが大変なのでは・・・と。


「ポインタ」とは何のことですか? children?
selectに関しては、通常親から順に検索していきますから問題ないでしょう。まさか主キーで
しか検索できないと考えているわけではないですよね?
insertに関しては、親オブジェクトへのポインタを子オブジェクトが持っていたほうが単純
になるでしょうね。つまり、Entryクラスにparent属性を持たせる、ということです。
てっく
常連さん
会議室デビュー日: 2002/11/05
投稿数: 28
投稿日時: 2004-01-08 18:55
ukさん、ありがとうございます。

引用:

ukさんの書き込み (2004-01-08 17:28) より:
「ポインタ」とは何のことですか? children?
selectに関しては、通常親から順に検索していきますから問題ないでしょう。まさか主キーで
しか検索できないと考えているわけではないですよね?



すみません、「ポインタ」とはprivate変数のchildrenを指していました。
SELECTで私が考えていたのは、
1:ParentIdがNULLであるレコードを取得しEntryにルートとして追加。
2:1のEntryId=ParentIdとなるレコードリストを取得しEntryに追加。
3:以下、階層の底まで繰り返す。
というやり方でした。
(下層から昇った方が良いのでしょうか?)
なんだか物凄い数のSQLを発行してしまうような。。。
同じ階層を一気にリストへ追加しながら階層を掘り下げていくのと、
階層を掘り下げながら徐々に同じ階層を充実させる方法では、
どちらが良いのでしょうか?

勿論Oracleのような商用RDBMSには階層問合せがサポートされているので、
SQLの発行を抑えることができるのですが、
MySQLのような(実は環境はMySQLです)RDBMSはまだまだそこまで進化していません。

根本的に考え方がずれているのでしょうか?
uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2004-01-08 19:10
引用:

てっくさんの書き込み (2004-01-08 18:55) より:
SELECTで私が考えていたのは、
1:ParentIdがNULLであるレコードを取得しEntryにルートとして追加。
2:1のEntryId=ParentIdとなるレコードリストを取得しEntryに追加。
3:以下、階層の底まで繰り返す。
というやり方でした。


オーソドックスなやり方はそうだと思います。

引用:

なんだか物凄い数のSQLを発行してしまうような。。。


えーと、全階層を一気に取得することが必要なのでしょうか? それとも処理が進むにつれて
必要な階層だけ取得すればいいのでしょうか? それによって実装方法は変わります。

引用:

同じ階層を一気にリストへ追加しながら階層を掘り下げていくのと、
階層を掘り下げながら徐々に同じ階層を充実させる方法では、
どちらが良いのでしょうか?


一般的な解はありません。あくまでどのように使われるかによります。

引用:

根本的に考え方がずれているのでしょうか?


いいえ、階層構造をRDBでどのように表現するかは非常に大きな問題です。ですが問題が
もう少し具体的にならないと答えは出ないでしょうね。
てっく
常連さん
会議室デビュー日: 2002/11/05
投稿数: 28
投稿日時: 2004-01-08 21:00
またまたukさん、ありがとうございます。

引用:

ukさんの書き込み (2004-01-08 19:10) より:
えーと、全階層を一気に取得することが必要なのでしょうか? それとも処理が進むにつれて
必要な階層だけ取得すればいいのでしょうか? それによって実装方法は変わります。



実は都道府県・市町村などの「地域情報データ」を、
このCOMPOSITEパターンで実現しようと考えていました。
これらはほとんど一定ですが、
要件上、どうしても頻繁にアクセスされてしまいます。
例えば
「関西地方」と絞った時に、
「大阪」や「京都」と言った都道府県情報から、
「大阪市」や「京都市」と言った市町村、更に・・・、
と言った下位の階層情報を一括して欲しい、という感じです。

毎回毎回SQLを発行したくないので、
いっそのことCOMPOSITEパターンを実装したオブジェクトに格納し、
(システム起動時か初めてのアクセス時に格納)
ユーザーのアクセス時はそちらのオブジェクトのみを見る、
というように考えています。
(無理にRDBMSに格納しておく必要も無いのですが・・・)
uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2004-01-08 21:10
引用:

てっくさんの書き込み (2004-01-08 21:00) より:
実は都道府県・市町村などの「地域情報データ」を、
このCOMPOSITEパターンで実現しようと考えていました。
これらはほとんど一定ですが、
要件上、どうしても頻繁にアクセスされてしまいます。
例えば
「関西地方」と絞った時に、
「大阪」や「京都」と言った都道府県情報から、
「大阪市」や「京都市」と言った市町村、更に・・・、
と言った下位の階層情報を一括して欲しい、という感じです。

毎回毎回SQLを発行したくないので、
いっそのことCOMPOSITEパターンを実装したオブジェクトに格納し、
(システム起動時か初めてのアクセス時に格納)
ユーザーのアクセス時はそちらのオブジェクトのみを見る、
というように考えています。


そういうことであれば、全情報を一気に読み込んでキャッシュしておくのがいいでしょう。
一回のSelectで全情報を読み込み、各レコードのParentのIDをチェックして階層構造を
再構成すればいいです。

引用:

(無理にRDBMSに格納しておく必要も無いのですが・・・)


まあどこに情報を持っておくかは好き好きですね。
1

スキルアップ/キャリアアップ(JOB@IT)