假设我有一个由三个表组成的以下简化示例数据库:
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时需要指定哪种关系?
答案 0 :(得分: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编辑上面这行“行”,您可以确定数据库中的模式是您的主要来源,并保存Schema :: Loader脚本以便再次运行,以便在数据库更改时自动重新生成类。
使用DBIx :: Class :: Schema :: Loader v0.05002无法正确处理上述模式的某些部分,因为Sinan设法找到了错误!如果“引用”部分和列名不在同一行上,则无法正确解析外键约束。
这个bug在DBICSL git中得到修复,但由于修复程序尚未发布,所以这里的关系应该是什么样的(我省略了列定义以节省空间;它们应该像当前生成的加载器一样它们)。
__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" },
{}
);
__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"
);
__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"
);