我在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();