在DBIx :: Class中使用自联接的组的组

时间:2010-09-08 13:32:31

标签: perl dbix-class

我正在尝试了解如何使用DBIx :: Class。

如果我想要记录组,使得组本身可以成为组的成员,我可能会创建一个包含以下内容的模式:

CREATE TABLE groups (
       id    INTEGER PRIMARY KEY,
       name  VARCHAR(100)
       );

CREATE TABLE group_groups (
       parent_id         INTEGER REFERENCES groups(id),
       child_id          INTEGER REFERENCES groups(id),
       PRIMARY KEY(parent_id,child_id)
       );

如果我使用DBIx :: Class :: Schema :: Loader转储此架构,我会得到以下关系:

Group.pm

__PACKAGE__->has_many(
  "group_groups_children",
  "Schema::Result::GroupGroup",
  { "foreign.child_id" => "self.id" },
  { cascade_copy => 0, cascade_delete => 0 },
);

__PACKAGE__->has_many(
  "group_groups_parents",
  "Schema::Result::GroupGroup",
  { "foreign.parent_id" => "self.id" },
  { cascade_copy => 0, cascade_delete => 0 },
);

GroupGroup.pm

__PACKAGE__->belongs_to(
  "child",
  "Schema::Result::Group",
  { id => "child_id" },
  {
    is_deferrable => 1,
    join_type     => "LEFT",
    on_delete     => "CASCADE",
    on_update     => "CASCADE",
  },
);

__PACKAGE__->belongs_to(
  "parent",
  "Schema::Result::Group",
  { id => "parent_id" },
  {
    is_deferrable => 1,
    join_type     => "LEFT",
    on_delete     => "CASCADE",
    on_update     => "CASCADE",
  },
);

我想我需要一个many_to_many关系桥,其中组表位于两侧,所以我创建了这个:

__PACKAGE__->many_to_many(
    'childgroups' => 'group_groups_children' , 'child');

__PACKAGE__->many_to_many(
    'parents' => 'group_groups_parents' , 'parent');

因为我对关系网桥定义的理解是这样的:'accessor_name'=> '相关表中has_many关系的名称','关联表中'belongs_to关系的名称'

当我尝试这段代码时:

my $group_rs = $schema->resultset('Group')->search(
        { id => $id }
);
my $group = $group_rs->first;
foreach my $child ($group->childgroups) {
<snip>

设置DBIC_TRACE显示SQL为:

SELECT child.id, child.name FROM group_groups me 
       JOIN groups child ON child.id = me.child_id  
       WHERE ( me.child_id = ? )

但我认为该行应该更像:

SELECT child.id, child.name FROM group_groups me 
       JOIN groups child ON child.id = me.child_id 
       JOIN groups parent ON parent.parent_id = me.id 
       WHERE ( me.child_id = ? )

如果有人建议我如何误解了many_to_many关系桥梁并纠正我的many_to_many功能定义,我将不胜感激。

1 个答案:

答案 0 :(得分:2)

在#dbix-class中询问后,ribasushi帮我解决了这个问题。显然,DBIC :: Schema :: Loader在Group.pm中创建了不正确的has_many关系,它应该如下所示:

__PACKAGE__->has_many(
  "group_groups_parents",
  "Schema::Result::GroupGroup",
  { "foreign.child_id" => "self.id" },
  { cascade_copy => 0, cascade_delete => 0 },
);

__PACKAGE__->has_many(
  "group_groups_children",
  "Schema::Result::GroupGroup",
  { "foreign.parent_id" => "self.id" },
  { cascade_copy => 0, cascade_delete => 0 },
);

原文:

has_many (group_groups_children => "Schema::Result::GroupGroup", { "foreign.child_id" => self.id" } )

表示“在child_id中具有我的id的所有行”,并且实际上是在他们的child.id中具有我的id的父母,而不是孩子。

我的架构很好,我的关系定义很好,我的使用代码很好,只是自动生成的关系不是,我的理解不足以发现失败。

ribasushi暗示命名约束(即我的架构的“更好”DDL可能导致DBICSL正确使用。