数据库应用开发:从单机到 Web 的实现与优化
1. 项目实现概述
在项目开发中,实现环节至关重要,它涉及到选择合适的编程语言和 API,进行面向对象设计并编写代码。对于本项目,我们需要快速开发出一个多功能的程序,并且要考虑到程序未来的扩展性。
1.1 语言和 API 选择
选择编程语言时需综合考虑多方面因素。由于要快速得到最终产品,且程序应具备扩展性,我们选择了 Perl。不过,Python、C++ 或 PHP 也是不错的选择。Perl 在 Linux 和数据库领域广受欢迎,它易于 shell 程序员快速掌握,结构也符合 C 程序员的习惯,同时还是一种支持继承(包括多重继承)和数据保护的面向对象语言。在最近的一项针对 Linux 用户的脚本语言调查中,Perl 在非 Web 编程的脚本语言中排名第一。
1.2 面向对象编程基础
面向对象编程是一种设计和实现代码的方式,它将方法(函数)和数据捆绑在一起,形成类,类是创建对象的框架,对象是类的实例。以下是面向对象编程中的一些常见术语及在 Perl 中的实现示例:
|术语|解释|Perl 示例|
| ---- | ---- | ---- |
|对象(Object)|也称为类的实例,数据和方法封装在一起|
$table; # 具有表的数据属性和方法
|
|构造函数(Constructor)|初始化对象|
$table=customer-> new(); # $table 现在具有与 customer 相关的数据属性
|
|属性(Attributes)|对象的数据(属性),不应直接访问|
$table->{STATE_CD} # 对象的最终用户不需要看到这个
|
|方法(Method)|对象可以执行的任务,通常称为对象的行为|
$query=$table->delete("customer_xyz"); # 编写删除客户 xyz 的查询
|
|封装(Encapsulation)|隐藏对象属性的存储方式和位置| - |
|继承(Inheritance)|使用另一个类的方法|
$table-> action_menu(); # 使用菜单类的 action_menu 方法
|
1.3 客户类(Customer Class)
客户类是一个用 Perl 编写的类,它展示了一些实用的面向对象技术。该类以 Customer 表为模型,可执行给表属性赋值、插入数据、删除行和浏览表等操作。以下是客户类的代码:
#!/usr/bin/perl
package customer;
use menu;
# inherit methods from menu
@ISA = ("menu");
sub new {
my $proto=shift;
my $class=ref($proto) || $proto;
my $self={};
$self->{FIRST_NAME}=undef;
$self->{MIDDLE_INITIAL}=undef;
$self->{LAST_NAME}=undef;
$self->{ADDRESS_LINE_1}=undef;
$self->{ADDRESS_LINE_2}=undef;
$self->{CITY}=undef;
$self->{STATE}=undef;
$self->{ZIP}=undef;
$self->{CUSTOMER_ID}=undef;
$self->{PHONE_NUMBER}=undef;
bless($self,$class);
return $self;
}
sub zip {
my $self = shift;
if (@_) { $self->{ZIP} = shift }
return $self->{ZIP};
}
# 其他方法如 phone_number、customer_id 等类似,此处省略
sub primary_key {
my $self = shift;
if (@_) { $self->{CUSTOMER_ID} = shift }
return $self->{CUSTOMER_ID};
}
sub insert {
my $self = shift;
# Connect to database
my $dbname='order_entry_db';
my $user='dba';
my $password='dba2pass';
my $dbd='mysql';
my $dbh=DBI->connect($dbname, $user, $password, $dbd);
if (!$dbh) {
print "ERROR connecting to database; $DBI::errstr\n";
}else {
print "connecting to database\n";
}
# create local values to use
my $cust_id=$self->customer_id;
my $first_name=$self->first_name;
my $middle_initial=$self->middle_initial;
my $last_name=$self->last_name;
my $address_line_1=$self->address_line_1;
my $address_line_2=$self->address_line_2;
my $city=$self->city;
my $state=$self->state;
my $zip=$self->zip;
my $phone_number=$self->phone_number;
# create query
my $query="insert into customer values ( $cust_id','$first_name',
$middle_initial','$last_name',
$address_line_1','$address_line_2',
$city','$state','$zip',
$phone_number','N')";
# execute query
print "preparing and executing sql.\n";
my $sth=$dbh->prepare("$query");
my $error=$sth->execute;
$sth->finish;
$dbh->disconnect();
return $error;
}
# browse 和 delete 方法类似,此处省略
1;
客户类虽然能处理表的各种操作,但存在一些可优化的地方,例如数据库连接信息硬编码多次,可将其作为构造函数的参数或类数据,以提高类的通用性。
1.4 菜单类(Menu Class)
菜单类是表类的超类,具有通用性,任何具有哈希数据类型的对象都可访问该类。部分菜单是动态构建的,如字段菜单;部分是静态构建的,如表格菜单。以下是菜单类的代码:
#!/usr/bin/perl
package menu;
use DBI;
@ISA=("DBI");
sub new {
my $proto=shift;
my $class=ref($proto) || $proto;
my $self={};
bless($self,$class);
}
sub table_menu {
print ("Welcome..
Please select a table from the following list or quit [q]:
1) Product
2) Customer
3) Order Header
4) Order Detail
Make your selection: ");
my $selection=<STDIN>;
if ($selection == 1) {
return 1;
}elsif( $selection == 2) {
return 2;
}elsif ( $selection == 3) {
return 3;
}elsif( $selection == 3) {
return 4;
} elsif ($selection =~ m/[qQ]/) {
die "Exiting application at users request.\n";
} else { action();}
}
# 其他方法如 action_menu、field 等类似,此处省略
这个流程图展示了菜单类中
table_menu
方法的执行流程:
graph TD;
A[开始] --> B[显示菜单选项];
B --> C[获取用户输入];
C --> D{输入是否为 q/Q};
D -- 是 --> E[退出应用];
D -- 否 --> F{输入是否为 1};
F -- 是 --> G[返回 1];
F -- 否 --> H{输入是否为 2};
H -- 是 --> I[返回 2];
H -- 否 --> J{输入是否为 3};
J -- 是 --> K[返回 3];
J -- 否 --> L{输入是否为 4};
L -- 是 --> M[返回 4];
L -- 否 --> N[执行 action() 方法];
1.5 主程序
主程序使用上述类来实现菜单驱动的用户界面。代码如下:
#!/usr/bin/perl
use customer;
use product;
use order_detail;
use order_header;
use strict;
# Strict requires this definition
my $table=undef;
my $table_choice=menu->table_menu();
if($table_choice==1) {
$table=product->new();
}elsif($table_choice==2) {
$table=customer->new();
}else { die "ERROR Line 25\n"; }
my $action=$table->action_menu();
if($action==1) {
my $continue=$table->field();
if($continue) {
print "inserting customer into table ..\n";
my $query=$table->insert();
my $sth=$dbh->prepare("$query");
my $error=$sth->execute;
}
}
elsif($action==2) {
my $pkey=$table->delete_menu;
if($pkey) {
$table->primary_key($pkey);
my $query=$table->delete();
print "deleting row where primary key is $pkey. \n";
my $sth=$dbh->prepare("$query\n");
my $error=$sth->execute;
}
}
elsif($action==3) {
my $continue=$table->browse_menu;
if ($continue) {
my $query=$table->browse();
my $sth=$dbh->prepare("$query\n");
my $error=$sth->execute;
my @fields=undef;
while(@fields=$sth->fetchrow_array) {
print "@fields\n";
}
}
}
$dbh->disconnect();
主程序通过调用菜单类和客户类等,实现了用户选择表、执行操作(插入、删除、浏览)的功能。但目前代码存在一些不足,如使用数字返回码不够灵活,菜单类可以返回表名,结合只需表名就能构造自身的表类,可使程序更具通用性。
2. 从单机应用到 Web 应用的转变
2.1 新的业务需求
之前开发的单机应用的商业客户提出了一些新的需求。由于经济环境的变化,客户希望开始通过互联网接受订单。具体要求如下:
1.
登录页面
:客户需要登录网站,因此需要一个登录页面。
2.
购买历史查询
:在订单数据库中查询客户的购买历史,所以客户使用的登录 ID 必须存在于订单录入数据库中,或者通过某种外键关系进行关联。
3.
订单页面
:需要一个用于下单的网页,并且要让客户清楚如何使用。
4.
折扣计算与显示
:自动计算折扣(如果有),并在订单表单上显示节省的金额。
2.2 技术选型
经过深思熟虑,我们决定使用 PHP 来实现网页和与订单录入数据库的接口。这种方法有以下优点:
-
服务器端执行
:PHP 可以在服务器端执行数据库访问,而不像 Java 需要在客户端运行安全的小程序。
-
MySQL 支持
:我们仍然使用 MySQL 作为数据库,PHP4 已经包含了对 MySQL 的支持,而使用 PHP3 时,需要使用
-with - mysql = DIR
选项进行安装。
2.3 数据模型集成与示例代码
结合给定的数据模型,我们可以通过以下示例 PHP 代码来实现集成,通过扩展这些示例可以创建更复杂的应用。以下是一个简单的登录验证示例:
<?php
// 数据库连接信息
$servername = "localhost";
$username = "dba";
$password = "dba2pass";
$dbname = "order_entry_db";
// 创建连接
$conn = new mysqli($servername, $username, $password, $dbname);
// 检查连接
if ($conn->connect_error) {
die("连接失败: " . $conn->connect_error);
}
// 获取用户输入
$loginID = $_POST['loginID'];
$password = $_POST['password'];
// 查询用户信息
$sql = "SELECT * FROM customers WHERE loginID = '$loginID' AND password = '$password'";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
// 用户验证成功
session_start();
$_SESSION['loginID'] = $loginID;
header("Location: order_page.php");
} else {
// 用户验证失败
echo "用户名或密码错误";
}
$conn->close();
?>
这个代码示例展示了一个基本的登录验证流程,流程图如下:
graph TD;
A[开始] --> B[连接数据库];
B --> C[获取用户输入的登录 ID 和密码];
C --> D[查询数据库验证用户];
D --> E{用户是否存在};
E -- 是 --> F[创建会话并跳转至订单页面];
E -- 否 --> G[显示错误信息];
F --> H[结束];
G --> H;
2.4 订单页面与折扣计算
以下是一个简单的订单页面示例,包含折扣计算功能:
<?php
session_start();
if (!isset($_SESSION['loginID'])) {
header("Location: login.php");
}
// 数据库连接信息
$servername = "localhost";
$username = "dba";
$password = "dba2pass";
$dbname = "order_entry_db";
// 创建连接
$conn = new mysqli($servername, $username, $password, $dbname);
// 检查连接
if ($conn->connect_error) {
die("连接失败: " . $conn->connect_error);
}
// 查询用户购买历史
$loginID = $_SESSION['loginID'];
$sql = "SELECT SUM(total_amount) as total_purchase FROM orders WHERE customer_id = (SELECT customer_id FROM customers WHERE loginID = '$loginID')";
$result = $conn->query($sql);
$row = $result->fetch_assoc();
$total_purchase = $row['total_purchase'];
// 计算折扣
$discount = 0;
if ($total_purchase > 150) {
$discount = 0.1; // 10% 折扣
}
// 显示订单页面
echo "<h1>订单页面</h1>";
echo "<p>您的总消费金额: $total_purchase</p>";
echo "<p>本次订单折扣: $discount%</p>";
// 模拟商品列表
$products = [
["id" => 1, "name" => "Product 1", "price" => 50],
["id" => 2, "name" => "Product 2", "price" => 100],
["id" => 3, "name" => "Product 3", "price" => 200]
];
echo "<form action='submit_order.php' method='post'>";
foreach ($products as $product) {
echo "<p>{$product['name']}: $ {$product['price']} <input type='number' name='quantity[{$product['id']}]' value='0'></p>";
}
echo "<input type='submit' value='提交订单'>";
echo "</form>";
$conn->close();
?>
这个代码示例展示了订单页面的基本结构和折扣计算逻辑,其操作步骤可以总结为:
1. 检查用户是否已登录,若未登录则跳转至登录页面。
2. 连接数据库,查询用户的购买历史。
3. 根据购买历史计算折扣。
4. 显示订单页面,包括商品列表和折扣信息。
5. 提供表单供用户输入商品数量并提交订单。
2.5 总结与展望
通过上述内容,我们展示了从单机数据库应用到 Web 应用的转变过程。在单机应用中,我们使用 Perl 进行面向对象编程,实现了菜单驱动的用户界面,处理了表的插入、删除和浏览等操作。而在 Web 应用中,我们根据新的业务需求,选择了 PHP 和 MySQL 技术栈,实现了用户登录、购买历史查询、订单页面和折扣计算等功能。
虽然目前的实现满足了基本需求,但仍有许多可以优化和扩展的地方。例如,在单机应用中,我们可以进一步优化客户类和菜单类,提高代码的通用性和可维护性;在 Web 应用中,我们可以加强安全性,防止 SQL 注入等攻击,同时可以优化用户界面,提高用户体验。通过不断地改进和完善,我们可以开发出更加健壮、高效和灵活的数据库应用程序。
总的来说,无论是单机应用还是 Web 应用,都需要我们在开发过程中充分考虑到未来的扩展性和变化,以确保应用程序能够适应不断变化的业务需求。这种基于生命周期的开发思想是成功开发数据库应用的关键,也是选择 Linux 和 UNIX 等操作系统的重要原因,因为这些操作系统本身就是为了便于重新设计和开发而设计的。
超级会员免费看
168万+

被折叠的 条评论
为什么被折叠?



