跳转到主要内容

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

所有提交的信息确保安全。

  • 关闭 [x]

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

所有提交的信息确保安全。

  • 关闭 [x]

功能丰富的 Perl:用 Perl保存

数据持久性的 CPAN 解决方案

Teodor Zlatanov 于 1999 年毕业于波士顿大学,并获得计算机工程硕士学位。他从 1992 年起就成为程序员,并开始用 Perl、Java、C 和 C++。他的兴趣在于文本语法分析、三层客户机-服务器数据库体系结构、UNIX 系统管理、CORBA 和项目管理方面的开放源码工作。可通过 tzz@bu.edu与他联系。

简介: 数据存储是计算机编程中常见的问题。CPAN <i>Persistent</i> 类通过一个简化数据创建、检索和管理的通用接口,使数据存储变得简单。通过面向对象的方法,可以在项目中将 <i>Persistent</i> 类作为自己的数据类的父类透明地使用。

发布日期: 2000 年 7 月 01 日
级别: 初级
访问情况 : 1806 次浏览
评论: 


持久性介绍

所有程序员都有必须解决数据持久性问题的经历。例如,对于如将文档存入文件和将事务存入数据库等任务,即使最简单的应用程序也需要大量工作。可以将数据持久性定义为程序和存储设备之间达成的契约,该契约指定如何存储和检索数据。

CPAN 定义:
“CPAN 是综合 Perl 档案网络。综合:其目的是包含可能需要的所有 Perl 资料。档案:从 1999 年 9 月至今,已有 760 兆字节。网络:全世界有超过一百个 CPAN 镜像站点。”

本文集中讲述在作者和读者事先都知道对象属性的情况下,如何使对象属性持久。本文不讨论动态发现对象属性和存储属性以外的特性(如行为)的主题,因为需要很多篇幅才能把这些主题讲清楚。

熟悉面向对象编程、数据库、Perl 和 Perl 继承将对阅读本文有帮助。

使对象属性持久只是软件开发过程的一小部分。首先,必须确定持久性的需求。需要保存什么?需要恢复什么?在恢复存储的数据之前,需要手工编辑吗?诸如此类的问题将确定软件如何将持久数据归档。不幸地是,没有一份调查表可以确定项目确切的持久性需要。软件设计师必须通过智能设计,定义并满足项目需求。很重要的一点是,最后的解决方案要确实是问题的解决方案,而不只是时髦的行业词语。例如,XML 解决数据持久性问题的能力比只用砖头来建造房屋好不到哪里。


持久数据示例

Perl 文件 simple 显示了预定义的关键字集合如何能够实现简单的持久性。这种方法有很多问题:文件格式是任意的,只保存一个关键字集合,根本没有对象、数据值限制到一行文本等等。


Persistent 类的简单使用:Persistent::File

Persistent 类旨在使数据持久性变得简单。为此,您必须阅读文档。对于掌握处理持久数据的方便的预制类而言,这只是很小的代价。所以,先花上几分钟或几小时来做这件事,以后将节省您的时间。有关文档和示例,请参阅 Persistent 类主页(请参阅 参考资料)。

第一个示例 first 将基于 Persistent::File 模块文档中给出的 simple 示例,并将描述达到持久性的步骤。


清单 1:定义数据
my %problems = (
        'Homework 1, Problem 1' => [0,5,2],
        'Homework 1, Problem 2' => [1,8,5],
        'Homework 1, Problem 3' => [2,2,4],
        'Homework 1, Problem 4' => [3,0,3],
        'Homework 1, Problem 5' => [4,1,2],
           );

首先,定义要存储在数据存储器中的数据。在 Persistent 类中,数据存储器是抽象存储设备,例如,它可以是文件或数据库。该例是自包容的,但是数据也可能来自别处。


清单 2:使用 eval 来捕获错误
use English;
eval 
{
};
print "An error occurred: $EVAL_ERROR\n" if $EVAL_ERROR;

因为不希望程序在出现执行错误时终止,所以将所有操作放在 eval 语句中。English 模块使我们可以使用 $EVAL_ERROR 、而不是 $@ 来表示错误消息。


清单 3:定义数据存储器
# 从文件创建持久对象
my $equation = new Persistent::File('variables.txt');

我们在这里创建了新的 Persistent::File 对象,其内容将存储在文件 variables.txt 中。


清单 4:定义属性
$equation->add_attribute('name', 'ID', 'VarChar', undef, 80);
$equation->add_attribute('x', 'Persistent', 'Number', 0, 10);
$equation->add_attribute('y', 'Persistent', 'Number', 0, 10);
$equation->add_attribute('z', 'Persistent', 'Number', 0, 10);
$equation->add_attribute('answer', 'Transient', 'Number', undef, 10);

我们创建了五个属性:一个唯一标识、三个持久数据成员和一个非持久(暂时)数据成员。Persistent 类将自动创建必要的函数(例如,$equation->answer())来访问数据成员。


清单 5:清除数据存储器
$equation->restore_all();
$equation->delete while $equation->restore_next();

restore_all 方法检索整个数据存储器的内容。restore_where 和 restore 方法分别用来选择符合某些标准的对象和单一对象。delete 方法除去当前等式,restore_next 方法移至下一个恢复的对象。


清单 6:存储对象数据
# 现在将问题存储到数据存储器
foreach my $key (keys %problems)
{
  $equation->clear;
  $equation->name($key);
  $equation->x($problems{$key}->[0]);
  $equation->y($problems{$key}->[1]);
  $equation->z($problems{$key}->[2]);
  $equation->save;
}

我们清除旧属性,设置新属性,并将对象存储到数据存储器。因为刚刚清除过数据存储器,所以我们知道,不会有 name 键冲突,但是,通常要进行检查,以便在用 save 方法试图重写现有键时不会导致异常。


清单 7:检索 homework 1 等式
# 在数据存储器中查询 homework 1 中的等式
$equation->restore_where(qq{name =~ 'Homework 1'});
while ($equation->restore_next()) 
{
  # do something with each equation
}

最后,遍历数据存储器,查找那些 name 键包含字符串 'Homework 1' 的对象,然后对这些对象中的每一个执行操作。

这个例子本身并不使人难忘,但是,请考虑:

  • 现在可以将任何数量的属性添加到持久对象
  • 可以有选择地检索任何存储的对象
  • 任何知道对象属性的其它程序都可以使用同样的数据存储器(这方面的详细信息在 “从 Persistent 类继承”中)。

通过使用预制的模块,我们已经用简单的方法解决了棘手的问题。这很有趣。


使用 Persistent::DBI

请阅读 Persistent::DBI 文档,来获得有关 Persistent::DBI 和 Persistent::Base 类之间区别的最新讨论。基本上,Persistent::DBI 允许我们连接到数据库,并在建立连接之后,象其它 Persistent::Base 类那样操作。可以将 清单 3 中显示的代码行用以下替代:


清单 8:定义要作为数据库的数据存储器
my $database = 'test_database';
my $host     = 'db_host';
my $user     = 'dali';
my $password = 'MeltingClocks';
my $table    = 'persistence_test_table';
my $equation = new Persistent::MySQL(
                  "DBI:mysql:database=$database;host=$hostname",
                  $user, 
                  $password, 
                  $table);

请注意,Persistent::MySQL 是 Persistent::DBI 的子类。只使用 Persistent::DBI 本身没什么用,必须使用特定于我们数据库的模块。令人欣慰的是,除了通过名称来引用 Persistent::MySQL 之外(例如 use 语句和 new 语句),在切换数据库时不需要更改代码。有关通过使用继承来将程序与数据库选项隔离的方法,请参阅 “从 Persistent 类继承”


清单 9:不同的查询语法
# 在数据存储器中查询 homework 1 中的等式
$equation->restore_where(qq{name LIKE '%Homework 1%'});

因为现在使用的是 SQL SELECT 语句,所以 restore_where 自变量从 Perl 模式匹配改成 SQL WHERE 子句。

表必须事先存在,Persistent::MySQL 将不创建表。编写一个单独的程序来创建表,或者继承时在类中添加必需的功能。

表必需与属性定义匹配,例如,等式表的主数据库键必须也是 Persistent 类的主键。(这是在实现工作之前必须有良好设计的情况。)

清单 8清单 9 只显示了为使用 SQL 而必须在 first 中做的更改。脚本 second 包含这些更改。


从 Persistent 类继承

文件 Equation.pm 包含从 Persistent::DBI 类继承所需的所有代码。很简单,不是吗?基本上,在本地 initialize 方法中执行 add_attribute 调用。在这里还可以做更多操作:例如,如果数据库中不存在表,则创建表。但是,基本方法很简单。

安全性注意事项:
通常,只有数据库中的特权用户才能创建表,所以最好与数据库管理员讨论表的创建,以确保不会因为安全性策略而导致您辛苦创建的表无法工作。

清单 10:Equation.pm 模块,扩展 Persistent::MySQL
#! /usr/bin/perl -w
package Equation;
@ISA = qw(Persistent::MySQL);
use strict;
use Persistent::MySQL;
sub initialize
{
  my $self = shift;
  $self->SUPER::initialize(@_);
 
  # define attributes of the object (the contract)
  # this is the primary object identifier key, a 10-character name
  $self->add_attribute('name', 'ID', 'VarChar', undef, 80);
  # x, y, and z are persistent numbers with default values of 0 and length of 10
  $self->add_attribute('x', 'Persistent', 'Number', 0, 10);
  $self->add_attribute('y', 'Persistent', 'Number', 0, 10);
  $self->add_attribute('z', 'Persistent', 'Number', 0, 10);
  # this attribute will NOT be saved
  $self->add_attribute('answer', 'Transient', 'Number', undef, 10);
}
1;

请注意 @ISA 这行,它告述 Perl:Equation 类从 Persistent::SQL 继承。

文件 third是文件 second 去掉 add_attribute 行和 "use Persistent::MySQL",而添加了清单 11 的结果:


清单 11:新的 use 语句
use lib '.';
use Equation;

这告诉 Perl 使用 Equation 模块 equation ,并在当前目录中查找 Equation.pm。

这里显示的方法可以轻易扩展到复杂得多的问题。 参考资料中的信息应该足以使您达到此目标。


结束语

CPAN Persistent 类是您搜索数据持久性解决方案时的有力帮手。通过使用,您将发现,使用 Persistent 类的最好方法是继承它们。请记住,在实现成功的数据持久性时,好的设计和属性的清晰定义与 Persistent 类同等重要。


参考资料

  • 您可以参阅本文在 developerWorks 全球站点上的 英文原文.

  • Dave Winters 的 Persistent 类主页(英) 上有关于 Persistent 类的详细信息,也可以在 CPAN 搜索页上找到。

  • CPAN(英) (综合 Perl 档案网络)(Comprehensive Perl Archive Network) 包含所有想要的 Perl 模块。

  • 有关 Perl 的所有信息,请参阅 perl.com(英)

  • Larry Wall、Tom Christiansen 和 Randal L. Schwartz 所著的 Programming Perl, 2nd Edition (O'Reilly, 1996) 是现今最好的 Perl 指南,但是与现在的 5.005 和 5.6.0 相比有些过时。

  • Damian Conway 所著的 Object Oriented Perl (Manning Publications, 2000) 是一本有关模块和面向对象的极佳指南。

  • Joseph Hall 和 Randal Schwartz 所著的 Effective Perl Programming (Addison Wesley, 1998) 是关于语言(而不是特定任务)的 Perl 技巧和窍门的权威书籍。

  • James Hoffman 的 SQL 指导教程(英) 是一个非常有用和有趣的指导教程,它带有到更多 SQL 信息的大量链接。极力推荐。

  • 参阅 "perltoot" 和 DBI perldoc 页面。

  • 本文引用的 Perl 文件和模块:

关于作者

Teodor Zlatanov

Teodor Zlatanov 于 1999 年毕业于波士顿大学,并获得计算机工程硕士学位。他从 1992 年起就成为程序员,并开始用 Perl、Java、C 和 C++。他的兴趣在于文本语法分析、三层客户机-服务器数据库体系结构、UNIX 系统管理、CORBA 和项目管理方面的开放源码工作。可通过 tzz@bu.edu与他联系。

关于报告滥用的帮助

报告滥用

谢谢! 此内容已经标识给管理员注意。


关于报告滥用的帮助

报告滥用

报告滥用提交失败。 请稍后重试。


developerWorks:登录


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 使用条款

 


当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

请选择您的昵称:

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

(长度在 3 至 31 个字符之间)


单击提交则表示您同意developerWorks 的条款和条件。 使用条款.

 


为本文评分

评论

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Linux
ArticleID=52761
ArticleTitle=功能丰富的 Perl:用 Perl保存
publish-date=07012000
author1-email=tzz@bu.edu
author1-email-cc=tzz@bu.edu

标签

Help
使用 搜索 文本框在 My developerWorks 中查找包含该标签的所有内容。

使用 滑动条 调节标签的数量。

热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。

我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。

使用搜索文本框在 My developerWorks 中查找包含该标签的所有内容。热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。