【发布时间】:2018-02-13 19:26:22
【问题描述】:
我在 Dancer2 项目中使用 DBIx::Class 与 MySQL 数据库通信。在那个项目中,我有一个 ClassInfo 结果集,我可以毫无问题地从中进行选择、搜索、删除和更新。
但是,每当我尝试添加新行时,通过:
my $new_class = $SCHEMA->resultset( 'ClassInfo' )->new({});
或
my $new_class = $SCHEMA->resultset( 'ClassInfo' )->create({});
(为简洁起见,省略了数据),我收到以下错误:
DBIx::Class::Row::has_column_loaded(): Can't call has_column data as class method at /home/jlamey/src/dancer_projects/QP/bin/../lib/QP.pm line 2109
2104 {
2105 flash error => sprintf( 'Class <strong>%s</strong> already exists.' );
2106 redirect '/admin/manage_classes/classes';
2107 }
2108
2109 my $new_class = $SCHEMA->resultset( 'ClassInfo' )->new(
2110 {
2111 title => body_parameters->get( 'title' ),
2112 description => body_parameters->get( 'description' ),
2113 class_group_id => body_parameters->get( 'class_group_id' ),
2114 class_subgroup_id => ( body_parameters->get( 'class_subgroup_id' ) ? body_parameters->get( 'class_subgroup_id' ) : undef ),
我什至尝试使用 零 数据同时提交“新建”和“创建”命令,以确保不是数据导致错误,并且仍然抛出错误。
它试图写入的表如下所示:
+----------------------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------------+---------------------+------+-----+---------+----------------+
| id | int(8) unsigned | NO | PRI | NULL | auto_increment |
| class_group_id | int(8) unsigned | NO | MUL | 1 | |
| class_subgroup_id | int(8) unsigned | YES | MUL | NULL | |
| teacher_id | int(8) unsigned | YES | MUL | NULL | |
| secondary_teacher_id | int(8) unsigned | YES | MUL | NULL | |
| tertiary_teacher_id | int(8) unsigned | YES | MUL | NULL | |
| title | varchar(255) | NO | MUL | | |
| description | text | NO | | NULL | |
| num_sessions | varchar(255) | YES | | NULL | |
| fee | varchar(100) | YES | | NULL | |
| skill_level | varchar(255) | YES | | NULL | |
| is_also_embroidery | tinyint(1) unsigned | YES | MUL | 0 | |
| is_also_club | tinyint(1) unsigned | YES | MUL | 0 | |
| show_club | tinyint(1) unsigned | YES | | 0 | |
| image_filename | varchar(255) | YES | | NULL | |
| supply_list_filename | varchar(255) | YES | | NULL | |
| no_supply_list | tinyint(1) unsigned | YES | | 0 | |
| always_show | tinyint(1) unsigned | YES | | 0 | |
| anchor | varchar(5) | YES | | NULL | |
| new | tinyint(1) unsigned | YES | | 0 | |
+----------------------+---------------------+------+-----+---------+----------------+
结果集如下所示:
package QP::Schema::Result::ClassInfo;
use base qw/DBIx::Class::Core/;
__PACKAGE__->table( 'classes' );
__PACKAGE__->add_columns(
id =>
{
data_type => 'integer',
size => 8,
is_nullable => 0,
is_auto_increment => 1,
},
.
.
.
new =>
{
data_type => 'boolean',
is_nullable => 0,
default_value => 0,
},
);
__PACKAGE__->set_primary_key( 'id' );
__PACKAGE__->belongs_to( teacher => 'QP::Schema::Result::Teacher', 'teacher_id' );
__PACKAGE__->belongs_to( teacher2 => 'QP::Schema::Result::Teacher', 'secondary_teacher_id' );
__PACKAGE__->belongs_to( teacher3 => 'QP::Schema::Result::Teacher', 'tertiary_teacher_id' );
__PACKAGE__->belongs_to( class_group => 'QP::Schema::Result::ClassGroup', 'class_group_id' );
__PACKAGE__->belongs_to( subgroup => 'QP::Schema::Result::ClassSubgroup', 'class_subgroup_id' );
__PACKAGE__->has_many( dates => 'QP::Schema::Result::ClassDate', 'class_id' );
1;
我很茫然;此项目中没有其他结果集存在此问题,并且它们都是以相同的方式构建的。
提前感谢您的帮助。 -- 杰森
【问题讨论】:
-
抛开实际问题不谈,教师 ID 的那三列设计不佳。您可能应该规范化您的数据库并使用 n-m 关系,以便每个班级可以有任意数量的教师。
-
你能解释一下你的意思吗?我想我在概念上理解,但不确定我是否清楚。有一个“教师”表,这三列引用该表,因为每个班级列表可以有 0 到 3 名列出的教师。
-
这与您看到的问题无关,但可以肯定。您的表格未标准化。对于只有 0 到 2 位教师的每个班级条目(行),您都有空列。仅当所有三个字段都填写时,才使用空间。这会使数据库膨胀。此外,如果您出于某种原因必须添加第四位教师,您将不得不更改 DDL 以添加另一列,从而导致对该表中的每一行进行写入操作以添加 NULL 字段。这是非常低效的。相反,您应该有一个用于映射该关系的 classes_teachers 表......
-
新表建立了 N:M 关系,其中每个演讲可以有任意数量的零个或多个老师,并且每个老师可以教多个班级。如果需要,可以在应用层中添加每个类三个的限制。对于 DBIC,它将是一个
has_many关系,并且您将有一个附加的 ResultClass。但总的来说,这是一种更高效的设计。 -
啊,我明白你在说什么。改为使用多对多关系映射。是的,这更有意义。而且,这是一个相当简单的变化。感谢您指出这一点。
标签: mysql perl dbix-class dancer