不使用数据库我想构建一个新的DBIx :: Class对象(歌曲)并附加一些多对多关联对象(标记)。然后我想以这种方式访问标签:
my @tags = $song->tags();
如果我先将对象插入数据库,我已经可以这样做,但如何在不使用insert()的情况下执行此操作?
下面是我输出已创建标签名称的代码。现在我想在不使用insert的情况下实现这一点。
这只是测试代码。否则,我有一个与MySql一起使用的更复杂的模式。现在我也使用Solr,我想将Solr响应转换为DBIx :: Class对象(不访问db)。
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
package MySchema::Song;
use base 'DBIx::Class';
__PACKAGE__->load_components('Core');
__PACKAGE__->table("artist");
__PACKAGE__->add_columns(
id => { data_type => 'integer', is_nullable => 0, is_auto_increment => 1 },
name => { data_type => 'varchar', is_nullable => 1, },
);
__PACKAGE__->set_primary_key('id');
__PACKAGE__->has_many('song_tag' => 'MySchema::SongTag', 'song_id');
__PACKAGE__->many_to_many('tags' => 'song_tag', 'tag');
package MySchema::Tag;
use base 'DBIx::Class';
__PACKAGE__->load_components('Core');
__PACKAGE__->table("tag");
__PACKAGE__->add_columns(
id => { data_type => 'integer', is_nullable => 0, is_auto_increment => 1 },
name => { data_type => 'varchar', is_nullable => 1, },
);
__PACKAGE__->set_primary_key('id');
__PACKAGE__->has_many('song_tag' => 'MySchema::SongTag', 'tag_id');
__PACKAGE__->many_to_many('songs' => 'song_tag', 'song');
package MySchema::SongTag;
use base 'DBIx::Class';
__PACKAGE__->load_components('Core');
__PACKAGE__->table("song_tag");
__PACKAGE__->add_columns(
song_id => { data_type => 'integer', is_nullable => 0 },
tag_id => { data_type => 'integer', is_nullable => 0 },
);
__PACKAGE__->set_primary_key( qw(song_id tag_id) );
__PACKAGE__->belongs_to('song' => 'MySchema::Song','song_id');
__PACKAGE__->belongs_to('tag' => 'MySchema::Tag', 'tag_id');
package MySchema;
use base 'DBIx::Class::Schema';
__PACKAGE__->load_classes(qw(Song Tag SongTag));
package main;
my $schema;
$schema = MySchema->connect('dbi:SQLite:dbname=:memory:');
$schema->deploy;
my $song = $schema->resultset('Song')->new_result({ id => 1, name => 'Song name' });
my $tag = $schema->resultset('Tag')->new_result({ id => 1, name => 'Tag name' });
my $song_tag = $schema->resultset('SongTag')->new({
song => $song,
tag => $tag,
});
$song->add_to_tags($tag);
#$tag->add_to_songs($song); # one or another
$song->insert;
$tag->insert;
# This works if objects are previously inserted
foreach my $tag ($song->tags) {
print $tag->name."\n";
}
1;
答案 0 :(得分:0)
我找到了一个不太好的解决方案,但它可以在不访问数据库的情况下运行。要实现此功能,需要将SongTag和Tag对象缓存在Song对象中,否则$song->tags()
将访问db。
package main;
my $schema;
$schema = MySchema->connect('dbi:SQLite:dbname=:memory:');
$schema->deploy;
$schema->storage->debug(1);
my $song = $schema->resultset('Song')->new_result({ id => 1, name => 'Song name' });
my $tag = $schema->resultset('Tag')->new_result({ id => 98, name => 'Tag name' });
my $tag2 = $schema->resultset('Tag')->new_result({ id => 99, name => 'Tag name 2' });
# create many-to-many relations in memory without accessing database
my $rel = $schema->resultset('SongTag')->search(); # cretes empty resultset object
$rel->{related_resultsets}->{tag} = $schema->resultset('Tag')->search();
$rel->{related_resultsets}->{tag}->set_cache([ $tag, $tag2 ]);
$song->{related_resultsets}->{song_tag} = $schema->resultset('SongTag')->search();
$song->{related_resultsets}->{song_tag}->set_cache([ $rel ]);
foreach my $tag ($song->tags) {
print $tag->name."\n";
}
1;