歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Unix知識 >> 關於Unix >> 功能豐富的Perl:用Perl保存

功能豐富的Perl:用Perl保存

日期:2017/3/6 15:49:04   编辑:關於Unix
數據存儲是計算機編程中常見的問題。CPAN Persistent 類通過一個簡化數據創建、檢索和管理的通用接口,使數據存儲變得簡單。通過 面向對象 的方法,可以在項目中將 Persistent 類作為自己的數據類的父類透明地使用。 持久性介紹 所有 程序員 都有必須解決數
  數據存儲是計算機編程中常見的問題。CPAN Persistent 類通過一個簡化數據創建、檢索和管理的通用接口,使數據存儲變得簡單。通過面向對象的方法,可以在項目中將 Persistent 類作為自己的數據類的父類透明地使用。
  
  持久性介紹
  所有程序員都有必須解決數據持久性問題的經歷。例如,對於如將文檔存入文件和將事務存入數據庫等任務,即使最簡單的應用程序也需要大量工作。可以將數據持久性定義為程序和存儲設備之間達成的契約,該契約指定如何存儲和檢索數據。
  
  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 oclearcase/" target="_blank" >ccurred: $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 類同等重要。

Copyright © Linux教程網 All Rights Reserved