1

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

グループグループ.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",
  },
);

グループテーブルが両側にある多対多の関係ブリッジが必要だと思うので、これを作成しました:

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

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

リレーションシップ ブリッジの定義についての私の理解は次のようになるためです。

このコードを試したとき:

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 = ? )

誰かが私が多対多の関係ブリッジをどのように誤解しているのかを提案し、多対多の関数定義を修正してくれたら、感謝します.

4

1 に答える 1

2

#dbix-class で尋ねたところ、リバスシがこれを解決するのに役立ちました。どうやら、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 を持つ親です。

スキーマは適切で、関係の定義は適切で、使用コードも適切でしたが、自動生成された関係が適切ではなく、私の理解が失敗を発見するのに十分ではありませんでした。

ribashi は、名前付き制約 (つまり、私のスキーマの「より良い」DDL により、DBICSL が正しくなった可能性があることをほのめかしました。

于 2010-09-09T18:13:07.693 に答える