perl – 如何在DBIx :: Class中定义和使用many_to_many关系?
我在DB中有3个表,简化为:
book book_language language ===== <->> ============== <<-> ======== bookID book_languageID languageID title bookID language languageID 使用DBIx :: Class :: Schema :: Loader我生成了schema,其中有相应的Result类: Book BookLanguage Language 由于某些原因,Loader没有检测到这些表之间的many_to_many关系,所以我在Language类中自己定义了这样的关系: package R::RMT::Result::Language; ... __PACKAGE__->many_to_many('books' => 'book_language_rel','bookid_rel'); 在Book类中: 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 ... 我错了什么?我试着把文件中的碎片联系在一起,但显然我弄错了.我从未见过一个关于多少关系应该如何工作的完整例子. AFAIU,在Result类中定义关系应该在这个类中创建一个访问器.我怎么能看到所有经过处理的存取器?如果我尝试使用Data :: Printer转储ResultSet对象,我只看到列的访问器,但没有关系的访问器. 如果我尝试列表关系: say $schema->source('Book')->relationships; 我在这里看不到many_to_many关系(也不是那些由DBIx :: Class :: Schema :: Loader拾取的关系),只有has_manys和belongs_tos. 编辑.添加最简单的测试用例: 创建表并填充数据 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,3),(3,2),(4,3); 使用默认值生成架构: dbicdump -o dump_directory=./lib -o debug=1 My::Schema 'dbi:mysql:dbname=testbook' user password 在Book.pm中添加了many_to_many-definitions # 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,'password' ); my $book_rs = $schema->resultset('Book'); say $book_rs->languages(); 解决方法
首先请注意,many_to_many只生成辅助方法(访问器),但在连接和预取参数中不能使用它们的意义上不是“真实”关系.
示例代码的问题在于您尝试在结果集对象上调用结果方法(生成的“语言”). 例如,调用$rs-> first->语言将起作用. 如果你想要$book_rs中所有书籍的所有语言,你必须在形成many_to_many的两个关系上使用search_related.如果您预先获取两个数据库或者之前没有获取rs,则不会命中数据库,在这种情况下构建并执行优化查询. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |