группы групп, использующие самостоятельные объединения в DBIx :: Class - PullRequest
1 голос
/ 08 сентября 2010

Я пытаюсь понять, как использовать 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 в связанной таблице', 'имя отношения own_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мост отношений и коррEct мои определения функции many_to_many, я был бы признателен.

1 Ответ

2 голосов
/ 09 сентября 2010

Спросив в классе # dbix, Рибасуши помог мне решить эту проблему.По-видимому, DBIC :: Schema :: Loader создал неправильные отношения has_many в Group.pm и должен выглядеть следующим образом:

__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 ", и на самом деле именно родители имеют мой идентификатор в их child.id, а не дети.

Моя схема была хорошей, мои определения отношений были хорошими, мой код использования был хорошим, этобыло просто то, что автоматически сгенерированных отношений не было, и моего понимания было недостаточно, чтобы обнаружить сбой.

ribasushi намекнул, что именованные ограничения (т. е. «лучший» DDL для моей схемы мог привести к тому, что DBICSL понял все правильно.

...