gpt4 book ai didi

perl - 如何在 DBIx::Class 中定义和使用多对多关系?

转载 作者:行者123 更新时间:2023-12-04 18:59:02 25 4
gpt4 key购买 nike

我在数据库中有 3 个表,简化为:

book        book_language       language
===== <->> ============== <<-> ========
bookID book_languageID languageID
title bookID language
languageID

DBIx::Class::Schema::Loader我生成了模式,对应的 Result 类在哪里:
Book
BookLanguage
Language

由于某些原因 Loader没有检测到这些表之间的多对多关系,所以我在 Language 中自己定义了这样的关系类(class):
package R::RMT::Result::Language;
...
__PACKAGE__->many_to_many('books' => 'book_language_rel', 'bookid_rel');

并在 Book类(class):
package R::RMT::Result::Book;
...
__PACKAGE__->many_to_many('languages' => 'book_language_rel', 'languageid_rel');

现在我希望访问所有相关语言,如下所示:
my $dsn = "DBI:mysql:database=rkBook";
my $schema = R::RMT->connect( $dsn, 'user', 'pwd' );

my $book_rs = $schema->resultset('Book');
say $book_rs->languages();

但我得到了错误:
Can't locate object method "languages" via package "DBIx::Class::ResultSet" at ...

我做错了什么?我尝试将文档中的线索拼凑在一起,但显然我做错了。我从来没有见过一个完整的例子 many_to_many关系应该有效。

AFAIU,在 Result 类中定义关系应该在这个类中创建一个访问器。我怎么能看到所有生成的访问器?如果我尝试使用 Data::Printer 转储 ResultSet 对象我只看到列的访问器,但没有看到关系的访问器。

如果我尝试列出关系:
say $schema->source('Book')->relationships; 

我在这里看不到 many_to_many关系(也不是那些被 DBIx::Class::Schema::Loader 拾取的关系),只有 has_many s 和 belongs_to s。

编辑。添加最简单的测试用例:

创建表并填充数据
CREATE TABLE `book` (
`bookID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(255) COLLATE utf8_estonian_ci NOT NULL DEFAULT '',
PRIMARY KEY (`bookID`),
KEY `title` (`title`)
) ENGINE=InnoDB;

CREATE TABLE `language` (
`languageID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`language` varchar(255) COLLATE utf8_estonian_ci NOT NULL DEFAULT '',
PRIMARY KEY (`languageID`),
KEY `language` (`language`)
) ENGINE=InnoDB;

CREATE TABLE `book_language` (
`book_languageID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`bookID` int(10) unsigned DEFAULT NULL,
`languageID` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`book_languageID`),
UNIQUE KEY `book_language` (`bookID`,`languageID`),
CONSTRAINT `book_language_ibfk_1` FOREIGN KEY (`languageID`) REFERENCES `language` (`languageID`) ON DELETE SET NULL,
CONSTRAINT `book_language_ibfk_2` FOREIGN KEY (`bookID`) REFERENCES `book` (`bookID`) ON DELETE SET NULL
) ENGINE=InnoDB;

INSERT INTO language (language) VALUES ('estonian'), ('english'), ('polish');
INSERT INTO book (title) VALUES ('Eesti rahva ennemuistsed jutud'), ('Estonska-polska slovar'), ('21 facts about...'), ('Englis-Polish Dictionary');
INSERT INTO book_language (bookID, languageID) VALUES (1,1), (2,1), (2,3),(3,1),(3,2),(3,3),(4,2),(4,3);

使用默认值生成架构:
dbicdump -o dump_directory=./lib -o debug=1 My::Schema 'dbi:mysql:dbname=testbook' user password

已添加 many_to_many -定义在 Book.pm
# Created by DBIx::Class::Schema::Loader v0.07046 @ 2017-03-21 18:49:05
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ipamXRkSe+HLXGdTGwzQ9w
__PACKAGE__->many_to_many('languages' => 'book_languages', 'languageid');

而在 Language.pm
# Created by DBIx::Class::Schema::Loader v0.07046 @ 2017-03-21 18:49:05
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:nZyaWdriRpgEWDAcO3+CFw
__PACKAGE__->many_to_many('books' => 'book_languages', 'bookid');

运行这个脚本:
#!/usr/bin/env perl

use strict; use warnings; use 5.014; use utf8::all;
use My::Schema;

my $dsn = "DBI:mysql:database=testbook";
my $schema = My::Schema->connect( $dsn, 'user', 'password' );

my $book_rs = $schema->resultset('Book');
say $book_rs->languages();

最佳答案

首先注意many_to_many只生成辅助方法(访问器)但不是“真正的”关系,因为您不能在连接和预取参数中使用它们。

您的示例代码的问题在于您尝试在结果集对象上调用结果方法(生成的“语言”)。

调用 $rs->first->languages例如将工作。

如果您想要$book_rs 中所有书籍的所有语言你必须使用 search_related关于形成 many_to_many 的两种关系.如果您预取这两个或在这种情况下构建并执行优化查询之前不获取 rs,这将不会命中数据库。

关于perl - 如何在 DBIx::Class 中定义和使用多对多关系?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42927408/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com