Как мне настроить классы результатов DBIx :: Class в этом простом случае? - PullRequest
7 голосов
/ 18 февраля 2010

Предположим, у меня есть следующая упрощенная примерная база данных, состоящая из трех таблиц:

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 ?

1 Ответ

6 голосов
/ 18 февраля 2010

Вы знакомы с 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»). «РЕДАКТИРОВАТЬ ЭТУ ЛИНИЮ» (строка), вы можете решить, что схема в БД является вашим основным источником, и сохранить сценарий Schema :: Loader для повторного создания классов в случае изменения БД.

Обновление

Части вышеупомянутой схемы не обрабатываются правильно с DBIx :: Class :: Schema :: Loader v0.05002, потому что Синану удалось найти ошибку! Ограничения внешнего ключа не были проанализированы правильно, если часть «ссылки» и имя столбца не были в одной строке.

Ошибка исправлена ​​в git DBICSL, но так как исправление еще не выпущено, вот как должны выглядеть отношения (я опускаю определения столбцов, чтобы сэкономить место; они должны быть такими же, как в настоящий момент генерирует загрузчик) их).

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" },
    {}
);

Event.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"
);
...