我有一个想使用Apache::Session::File存储的Moose类。
但是,默认情况下,Apache::Session::File不会存储它,而是显示错误消息:
(in cleanup) Can't store CODE items at blib\lib\Storable.pm (autosplit into blib\lib\auto\Storable\_freeze.al)...
可以通过设置来解决此问题
$Storable::Deparse = 1;
$Storable::Eval = 1;
为了允许CODE引用被序列化。
下面列出了Moose类中令人反感的方法,该方法从mysql数据库中检索一列:
sub _build_cell_generic {
my ($self,$col) = @_;
my $sth = $self->call_dbh('prepare','select '.$col.' from '.$self->TABLE.' where CI = ? and LAC = ? and IMPORTDATE = ?');
$sth->execute($self->CI,$self->LAC,$self->IMPORTDATE);
my $val = $sth->fetchrow_array;
$sth->finish;
return defined $val ? $val : undef;
}
因此,大概dbh对象(isa DBIx::Connector)包含CODE引用。
为了允许对此Moose类进行序列化,是否有比设置$ Storable::Deparse和$ Storable::Eval更好的选择?
以下测试脚本会产生错误:
#!/usr/bin/perl -w
use Apache::Session::File;
use Test::More;
use strict;
use warnings;
require_ok( 'GSM::TestCell' );
require_ok( 'GSM::SQLConnection');
my $db = new_ok('GSM::SQLConnection');
my $cell4 = new_ok( 'GSM::TestCell' => [{LAC => 406, CI => 24491, DB => $db }] );
my %session;
tie %session, 'Apache::Session::File', undef, {Directory =>"./", LockDirectory => "./" };
print "BCCH is ",$cell4->BCCH,"\n";
$session{$cell4->ID} = $cell4;
done_testing();
__END__
SQL连接类定义为:
package GSM::SQLConnection;
#use DBI;
use Moose;
use DBIx::Connector;
has dbixc => (is => 'ro', isa => 'DBIx::Connector', lazy_build => 1, handles => [ qw(dbh) ]);
sub _build_dbixc {
my $self = shift;
my $dsn = 'DBI:mysql:testDB;host=127.0.0.1;port=3306';
return DBIx::Connector->new($dsn,'user','pwd');
}
sub call_dbh {
my $self = shift;
my $method = shift;
my @args = @_;
$self->dbixc->run(fixup => sub { $_->$method(@args) });
}
no Moose;
__PACKAGE__->meta->make_immutable;
1;
TestCell类定义为:
package GSM::TestCell;
use MooseX::NaturalKey;
use strict;
use warnings;
has [qw(LAC CI)] => (is => 'ro', required => 1);
has [qw(ID BCCH IMPORTDATE)] => (is => 'rw', lazy_build => 1);
has 'DB' => (is => 'rw', isa => 'GSM::SQLConnection', required => 1, );
has 'TABLE' => (is => 'rw', default => 'Cell');
primary key =>('LAC','CI');
sub _build_ID {
my $self = shift;
return join(',',$self->LAC,$self->CI);
}
sub _build_IMPORTDATE {return '2010-06-21'}
sub _build_BCCH {(shift)->_build_cell_generic('BCCHFrequency');}
sub _build_cell_generic {
my ($self,$col) = @_;
my $sth = $self->DB->call_dbh('prepare','select '.$col.' from '.$self->TABLE.' where CI = ? and LAC = ? and IMPORTDATE = ?');
$sth->execute($self->CI,$self->LAC,$self->IMPORTDATE);
my $val = $sth->fetchrow_array;
$sth->finish;
return defined $val ? $val : undef;
}
no Moose;
__PACKAGE__->meta->make_immutable;
1;
最佳答案
我真的怀疑您是否真的需要序列化代码引用;您所包含的示例没有任何示例。无论如何,您都不希望序列化DBIx::Connector对象,因为它们仅特定于当前运行时实例。
DBIx::Connector对象中可能包含一个小的coderef,因为通常将对dbh的访问包装在一个子对象中,以捕获documentation中连接消失的情况(请参阅“fixup”的讨论)。
Moose对象的序列化由MooseX::Storable处理,该扩展很容易扩展。您可以在其中自定义一个序列化程序以满足您的需要-即选择要序列化的属性和要忽略的属性。
关于perl - 使用Apache::Session和CODE引用存储Moose对象的替代方法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3069831/