我的(简化)SQLite表是这样的:
create table customers (
id integer primary key autoincrement,
contact_name text,
billaddr_id integer references addresses(id)
);
create table addresses (
id integer primary key autoincrement,
address text
);
以下是结果类(由dbicdump从sql生成):
Test::DB::Schema::Result::Customer->table("customers");
Test::DB::Schema::Result::Customer->add_columns(
"id",
{ data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
"contact_name",
{ data_type => "text", is_nullable => 1 },
"billaddr_id",
{ data_type => "integer", is_foreign_key => 1, is_nullable => 1 },
);
Test::DB::Schema::Result::Customer->set_primary_key("id");
Test::DB::Schema::Result::Address->table("addresses");
Test::DB::Schema::Result::Address->add_columns(
"id", { data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
"address", { data_type => "text", is_nullable => 1 },
);
Test::DB::Schema::Result::Address->set_primary_key("id");
Test::DB::Schema::Result::Address->has_many(
"customers",
"Test::DB::Schema::Result::Customer",
{ "foreign.billaddr_id" => "self.id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
Test::DB::Schema::Result::Customer->belongs_to(
"billaddr",
"Test::DB::Schema::Result::Address",
{ id => "billaddr_id" },
{
is_deferrable => 0,
join_type => "LEFT",
on_delete => "NO ACTION",
on_update => "NO ACTION",
},
);
这段代码:
my $data = {
contact_name => 'Jim Customer',
billaddr => {
address => 'Address...',
},
};
my $newcustomer = $c->schema->resultset('Customer')->create($data);
导致此数据库更新:
SELECT me.id, me.address FROM addresses me WHERE ( ( me.address = ? ) ): 'Address...'
BEGIN WORK
SELECT me.id, me.address FROM addresses me WHERE ( ( me.address = ? ) ): 'Address...'
INSERT INTO addresses ( address ) VALUES ( ? ): 'Address...'
INSERT INTO partners ( billaddr_id, contact_name ) VALUES ( ?, ? ) : '10', 'Jim Customer'
COMMIT
为什么在插入之前进行选择?因为它正在检查是否已存在具有相同“地址”列值的地址。如果确实存在,则重复使用该地址的ID,如下所示:
SELECT me.id, me.address FROM addresses me WHERE ( ( me.address = ? ) ): 'Address...'
INSERT INTO partners ( billaddr_id, contact_name ) VALUES ( ?, ? ): '10', 'Another Customer with the same address'
但那不是我想要的!我希望为不同的客户提供单独的地址,即使他们恰好住在同一个地方。
如何使DBIx :: Class每次在地址表中创建一个新行?
答案 0 :(得分:0)
感谢abraxxa的评论,我指出了正确的方向,并使用DBIx :: Class:Schema进行了更多的阅读和测试。
从Schema类生成表,而不是相反,似乎是要走的路,特别是如果它将来更容易升级到数据库。
我已将问题归结为以下示例代码:
Test.pl:
#!/usr/bin/perl
use Test::DB::Schema;
my $schema = Test::DB::Schema->connect(
"dbi:SQLite:dbname=dbicsl_test.db", '', '', {}
);
$schema->deploy({ add_drop_table => 1 } , '.');
$schema->storage->debug(1);
my $data1 = {
text => 'Fred',
table2 => {
text => 'abc',
}
};
my $new1 = $schema->resultset('Table1')->create($data1);
my $data2 = {
text => 'Jim',
table2 => {
text => 'xyz',
}
};
my $new2 = $schema->resultset('Table1')->create($data2);
my $data3 = {
text => 'Emily',
table2 => {
text => 'abc',
}
};
my $new3 = $schema->resultset('Table1')->create($data3);
测试:: DB ::架构::结果:: Table1.pm:
package Test::DB::Schema::Result::Table1;
use base 'DBIx::Class::Core';
__PACKAGE__->table("table1");
__PACKAGE__->add_columns(
"id",
{ data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
"text",
{ data_type => "text", is_nullable => 1 },
"table2_id",
{ data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
);
__PACKAGE__->set_primary_key("id");
__PACKAGE__->has_one(
table2 =>
"Test::DB::Schema::Result::Table2",
{ 'foreign.id' => 'self.table2_id' },
);
1;
测试:: DB ::架构::结果::表2:
package Test::DB::Schema::Result::Table2;
use base 'DBIx::Class::Core';
__PACKAGE__->table("table2");
__PACKAGE__->add_columns(
"id",
{ data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
"text",
{ data_type => "text", is_nullable => 0 },
);
__PACKAGE__->set_primary_key("id");
1;
这是输出:
SELECT me.id, me.text FROM table2 me WHERE ( me.text = ? ): 'abc'
BEGIN WORK
SELECT me.id, me.text FROM table2 me WHERE ( me.text = ? ): 'abc'
INSERT INTO table2 ( text) VALUES ( ? ): 'abc'
INSERT INTO table1 ( table2_id, text) VALUES ( ?, ? ): '1', 'Fred'
COMMIT
SELECT me.id, me.text FROM table2 me WHERE ( me.text = ? ): 'xyz'
BEGIN WORK
SELECT me.id, me.text FROM table2 me WHERE ( me.text = ? ): 'xyz'
INSERT INTO table2 ( text) VALUES ( ? ): 'xyz'
INSERT INTO table1 ( table2_id, text) VALUES ( ?, ? ): '2', 'Jim'
COMMIT
SELECT me.id, me.text FROM table2 me WHERE ( me.text = ? ): 'abc'
INSERT INTO table1 ( table2_id, text) VALUES ( ?, ? ): '1', 'Emily'
所以数据库现在看起来像
table1.id table1.text table1.table2_id
1 Fred 1
2 Jim 2
3 Emily 1
table2.id table2.text
1 abc
2 xyz
而我期望/希望:
table1.id table1.text table1.table2_id
1 Fred 1
2 Jim 2
3 Emily 3
table2.id table2.text
1 abc
2 xyz
3 abc
为什么当我没有告诉它使table2.text列唯一时,它会重用1 / abc?