2

所以。

对于我遇到的具体问题,也许这个标题太笼统了。

我有一个连接到 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。

我只是想知道是否有更聪明的方法可以做到这一点,所以我不必将数据库处理程序对象作为参数传递。

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

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

问候。

4

3 回答 3

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)。

于 2013-07-26T02:20:35.033 回答
3

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

Perldoc 上的 perlootut是 OO Perl 的一个不错的低级介绍,尽管当您在 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");
}
于 2013-07-26T02:37:21.960 回答
2

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

  • 对全局变量使用our范围别名。这不像 OO 方法那样整洁,但它通常工作得非常好,没有缺点——这是少数our推荐的情况之一。

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

  • 将其设置为真正的单例。此处讨论了该技术:如何在 perl 中实现单例类?

于 2013-07-26T02:35:14.173 回答