我有一个结构如此复杂的应用程序:
/root_dir/lib/Mojo_App/Controller/Main.pm
/root_dir/lib/Mojo_App/Database/Db.pm
/root_dir/ ...
在Database :: Db中,我有一个子例程,可创建与SQL SERVER的连接。该子例程在Main.pm中导出并使用
示例:
数据库:: DB
my $config = {
db1 => {
host => 'dbi:Driver:server=ip01;database=db01',
user => 'user01',
pass => 'pass01'
},
db2 => {
host => 'dbi:Driver:server=ip02;database=db02',
user => 'user02',
pass => 'pass02'
},
db3 => {
host => 'dbi:Driver:server=ip03;database=db03',
user => 'user03',
pass => 'pass03'
}
};
sub connect_db {
use DBI;
my $self = shift;
return 0 unless $self;
my $dbh;
if (exists($config->{$self})) {
return $dbh = DBI->connect($config->{$self}->{host}, $config->{$self}->{user}, $config->{$self}->{pass}) || die( $DBI::errstr . "\n" ) ;
} else {
return "Connection not in config. \n" ;
}
return $dbh;
}
在Main.pm中,我这样连接:
my $dbh = connect_db('db1');
现在可以说我需要在索引页面上连接到数据库,因此在Main.pm中将有一个子例程索引,如下所示:
sub index {
my $self = shift;
my $dbh = connect_db('db1');
...
$self->render();
}
现在,我不希望每次用户访问索引页面时都要建立新的连接,我想检查连接是否处于活动状态,以及是否不创建连接。
我已经阅读了有关ping方法的信息,但是我不知道如何在这里实现它。
我还阅读了有关DBIx的信息,并尝试了以下实现:
sub connect_db {
use DBIx::Connector;
my $self = shift;
return 0 unless $self;
my $dbh;
if (exists($config->{$self})) {
my $conn = DBIx::Connector->new($config->{$self}->{host}, $config->{$self}->{user}, $config->{$self}->{pass}, {
RaiseError => 1,
AutoCommit => 1,
});
return $dbh = $conn->dbh; ;
} else {
return "Connection not in config. \n" ;
}
return $dbh;
}
此实现能否实现我想要的?当数据库连接处于活动状态时将被使用且未重新创建。如果是,那么像Dbi一样使用DBIx是否安全?我在这里指的是:
my $dbh = $conn->dbh;
$dbh->do('INSERT INTO foo (name) VALUES (?)', undef, 'Fred' );
and not
$conn->run(fixup => sub {
$_->do('INSERT INTO foo (name) VALUES (?)', undef, 'Fred' );
});
谢谢
答案 0 :(得分:1)
使用DBIx :: Connector对象中的dbh
方法,然后将其用作常规DBI句柄是安全的,但是如果您不这样做,则可能会错过DBIx :: Connector的大多数优点。 t保留DBIx :: Connector对象。创建一个新的DBIx :: Connector对象将意味着需要一个新的连接,因为该对象是连接的缓存位置。此外,每当您调用->dbh
或->run
时,DBIx :: Connector都会检查该连接是否处于活动状态以及您是否未进行分叉,并在需要时建立新连接。因此,最好存储并传递DBIx :: Connector对象,然后让任何单独的代码段检索dbh
或调用run
。在Mojolicious应用程序中,通常将类似的内容存储在应用程序helper中(但当然,您可以将其放在方便的地方)。
# in application startup
my %dbs;
$app->helper(db => sub {
my ($c, $name) = @_;
return $dbs{$name} //= DBIx::Connector->new(...);
});
# elsewhere
my $dbh = $c->db('db1')->dbh;
# or
$c->db('db1')->run(...);
答案 1 :(得分:0)
DBI::connect_cached
应该解决的问题:
$dbh = DBI->connect_cached($data_source, $username, $password) or die $DBI::errstr; $dbh = DBI->connect_cached($data_source, $username, $password, \%attr) or die $DBI::errstr;
connect_cached
类似于“connect
”,除了返回的数据库句柄也存储在与给定参数关联的哈希中。如果使用相同的参数值再次调用connect_cached
,则如果仍然有效,则将返回相应的缓存$dbh
。如果已断开连接或ping
方法失败,则将缓存的数据库句柄替换为新的连接。
有关重要免责声明,请参阅文档。