Perl:如何避免全局并保持数据库连接

时间:2013-07-26 02:09:06

标签: database perl sqlite

SO。

对于我遇到的具体问题,标题可能过于笼统。

我有一个连接到SQLite数据库的Perl脚本。在运行期间,我执行了很多数据库操作,例如SELECT,INSERT,UPDATE等。我将每个数据库操作包装在它自己的子例程中(主要是为了隐藏SQL语句和结果集的任何其他处理)。

每次我需要调用此数据库操作子例程之一时,我想使用相同的数据库处理程序对象,所以我一直在做的是将数据库处理程序对象作为参数传递。例如:

my $dbh = DBI->connect( "dbi:SQLite:dbname=db.db", "", "") or die;

sub select_from_systems {
    my $dbh = shift;
    return $dbh->selectcol_arrayref("SELECT hostname FROM systems");
}

正如旁注,我正在使用Perl DBI。

我只是想知道是否有更聪明的方法来执行此操作,因此我不必将数据库处理程序对象作为参数传递。

我想避免全局变量,我不认为它们是瘟疫,在这种情况下它可能是合理的,但仍然。

非常感谢任何帮助或见解。

问候。

3 个答案:

答案 0 :(得分:4)

使您的模块面向对象。这仍然会将句柄作为参数传递,但语法更好。

package MyConnection;

sub new {
  my $class = shift;
  my $dbh = DBI->new(@_);
  bless \$dbh, $class;
}

sub select_from_systems {
    my $self = shift;
    $$self->selectcol_arrayref(...);
}

然后:

my $db = MyConnection->new(@credentials);
...;
my $result = $db->select_from_systems;

为了对对象建模,我在这里使用了一个简单的标量引用,但你可能想要传统的基于散列的OO(或者只是使用Moose)。

答案 1 :(得分:3)

这听起来像你应该考虑使用面向对象的Perl。如果您不熟悉面向对象编程,那么其中一个好处就是您可以拥有一组函数,这些函数都可以对某些常见数据进行操作(在本例中为数据库引用)。

对OO Perl的一个很好的低级别介绍是perlootut on Perldoc,尽管当你在Perl中进行大规模的面向对象编程时,使用像Moose这样的模块似乎很流行。

现在,在幕后,Perl仍然绕过对象(某种类型的引用,通常是散列引用),并且使用基本的OO Perl,函数本身仍然需要显式处理它。但是,它使调用语义更好,如下所示:

my $database_object = new DatabaseObject("dbi:SQLite:dbname=db.db");
$database_object->select_from_systems();

相应的函数定义类似于:

package DatabaseObject;
sub new {
    my $class = shift;
    my $dbpath = shift;
    my $dbh = DBI->connect( $dbpath, "", "") or die;

    my $self = {_dbh => $dbh};
    bless $self, $class;
    return $self;
}

sub select_from_systems {
    my $self = shift;
    return $self->{_dbh}->selectcol_arrayref("SELECT hostname FROM systems");
}

答案 2 :(得分:2)

如果您真的希望数据库处理程序是Singleton(例如每个Perl进程一个),您可以:

  • 对全局变量使用our作用域别名。这并不像OO方法那样整洁,但它通常可以很好地完成,没有任何缺点 - 这是少数几种推荐our的罕见情况之一。

  • 将其设置为our,但为其创建类级别(例如非对象)setter和getter方法。

  • 将其设置为真正的单身人士。这里讨论的技术是:How can I implement a singleton class in perl?