7

3 つのテーブルで構成される次の単純化されたサンプル データベースがあるとします。

CREATE TABLE people (
    person_id   INTEGER PRIMARY KEY,
    person_name VARCHAR(100)
);

CREATE TABLE events (
    event_id       INTEGER PRIMARY KEY,
    event_name     VARCHAR(100),
    event_creator  INTEGER
                   CONSTRAINT fk_event_creator REFERENCES people(person_id)
);

CREATE TABLE event_attendees (
    event_id  INTEGER NOT NULL
              CONSTRAINT fk_event_attendee_event
              REFERENCES events(event_id),
    person_id INTEGER NOT NULL
              CONSTRAINT fk_event_attendee_person
              REFERENCES people(person_id),
    role      CHAR(1), -- O: organizer, P: performer, S: speaker, G: guest
    CONSTRAINT pk_event_attendees PRIMARY KEY (event_id, person_id)
);

が与えられた場合event_id、すべての主催者の名前を照会したり、 が与えられたperson_id場合、この人物がイベントのゲストまたは作成者であるすべてのイベントの名前を検索したりしたい場合があります。

単純な SQL を使用してすべてを行う方法を知っています。DBIx::Classを使用する際に、どの結果クラスを設定する必要があり、どのような関係を指定する必要があるか教えていただけますか?

4

1 に答える 1

6

DBIx::Class::Schema::Loaderに精通していますか? ワンオフ スクリプトで DBIC スキーマをメモリ内に動的に作成するために使用できますが、スキーマ定義をディスクに書き込んで編集および構築できる「ワンショット」モードで実行することもできます。そして、それはあなたが思っているよりもはるかに進んでいます。

まず、ローダーがスキーマをスキャンできるように、スキーマをデータベースに実際に存在させたいと考えています。次に、次のようなことを行います。

perl -MDBIx::Class::Schema::Loader=make_schema_at \
-e 'make_schema_at("MyApp::Schema", {dump_directory=>"schema_out"},' \
-e '["dbi:DBType:connstring", "user", "pass"]);'

(ここで、「MyApp::Schema」は、生成されたスキーマ クラスで共有するパッケージ名であり、「schema_out」は、それらを生成するディレクトリです)。

この後、生成されたスキーマ クラスを編集できます。または、ローダーが十分な仕事をしていることがわかった場合 (または、少なくとも "DON'T EDIT ABOVE THIS LINE" 行)、DB 内のスキーマがプライマリ ソースであると判断し、Schema::Loader スクリプトを保存して、DB が変更された場合にクラスを自動的に再生成するために再度実行することができます。

アップデート

上記のスキーマの一部は DBIx::Class::Schema::Loader v0.05002 で正しく処理されません。Sinan がバグを発見したからです! 「参照」部分と列名が同じ行にない場合、外部キー制約が正しく解析されませんでした。

バグは DBICSL git で修正されていますが、修正がまだリリースされていないため、リレーションは次のようになります (スペースを節約するために列の定義を省略しています。現在ローダーが生成しているものと同じにする必要があります)。

EventAttendee.pm

__PACKAGE__->set_primary_key(qw(event_id person_id));

__PACKAGE__->belongs_to(
    "event" => "MyApp::Schema::Result::Event",
    { event_id => "event_id" },
    {}
);

__PACKAGE__->belongs_to(
    "person" => "MyApp::Schema::Result::Person",
    { person_id => "person_id" },
    {}
);

イベント.pm

__PACKAGE__->set_primary_key("event_id");

__PACKAGE__->belongs_to(
    "event_creator" => "MyApp::Schema::Result::Person",
    { person_id => "event_creator" },
    { join_type => "LEFT" },
);

__PACKAGE__->has_many(
    "event_attendees" => "MyApp::Schema::Result::EventAttendee",
    { "foreign.event_id" => "self.event_id" },
);

# Not auto-generated, but you probably want to add it :)
__PACKAGE__->many_to_many(
    "people_attending" => "event_attendees" => "person"
);

People.pm

__PACKAGE__->has_many(
    # It might be wise to change this to "events_created"
    "events" => "MyApp::Schema::Result::Event",
    { "foreign.event_creator" => "self.person_id" },
);

__PACKAGE__->has_many(
    "event_attendees" => "MyApp::Schema::Result::EventAttendee",
    { "foreign.person_id" => "self.person_id" },
);

# Not auto-generated, but you probably want to add it :)
__PACKAGE__->many_to_many(
    "events_attending" => "event_attendees" => "event"
);
于 2010-02-18T19:04:30.563 に答える