前言
目标
本课程的目标是帮助您完成以下操作:
- 下载和安装 MySQL 数据库服务器。
- 配置数据库与 JDBC 协作。
- 编写和测试您的第一个 JDBC 程序,用于管理数据库和操作存储在 MySQL 数据库中的数据。
什么是 JDBC?
JDBC 技术是一种应用程序编程接口(包括于 J2SE 和 J2EE),它提供对各种 SQL 数据库的交叉 DBMS 连接和对其它表列数据源(例如电子表格和平面文件)的访问。
什么是 MySQL?
MySQL 数据库可能是世界上最盛行的开放源码数据库软件,截止 2004 年 9 月,有效安装次数达 500 万以上。
MySQL 的数据库服务器软件可按照“双许可”模型使用。按照此模型,用户可以按照免费软件/开放源码 GNU 通用公共授权许可证 (通常称为“GPL”)或按照商业许可证使用 MySQL 产品。
功能强大的组合
简单地说,JDBC 使得编写可用于操作各种 SQL 数据库中数据的独立于平台的 Java 程序成为可能,而且在从平台迁移到平台,或者从 DBMS 迁移到 DBMS 时,不需要修改和/或重新编译 Java 程序。
MySQL 适用于各种平台。
由于 JDBC 和 MySQL 可随意用于许多用途,因此 JDBC 和 MySQL 的组合是一种适用于各种应用程序的功能强大的组合。
查看技巧
您会发现,在单独的浏览器窗口中打开本课程的另一副本非常有用。这将使您在阅读有关内容时,更易于前后滚动浏览不同的清单和图形。
补充材料
我建议,您还可以学习我的一系列 Java 在线教程中的其他课程。 您可以在 Gamelan.com 找到这些发布的课程。 但是,截止撰写本文之日,Gamelan 并不保留我的 Java 教程的统一索引,而且有时很难查找。 您可以在 www.DickBaldwin.com 查找统一索引。
下载、安装和准备数据库服务器
通常可以使用相同的 Java 程序操作各种 SQL 数据库中的数据,而且不需要修改和/或重新编译 Java 程序。
但是,不同 SQL 数据库的安装和准备流程有很大不同。使用 JDBC 连接特定数据库的一个重要问题是安装数据库,以及恰当准备数据库,以便与 JDBC 一起使用。
在本课程中,我将向您介绍如何下载、安装和准备 MySQL 数据库,作为 Windows 平台上的 localhost 服务器,以便与 JDBC 一起使用。 然后,我将向您介绍如何编写三个简单的 JDBC 程序,以便在安装数据库之后管理数据库服务器和操作存储在数据库服务器中的数据。
(我将假设您已在计算机中安装 Java SDK v1.4.2 或更高版本,其中包括 JDBC。)
用于下载的 URL 和版本号
我将提供截止 2004 年 9 月用于下载 MySQL 软件和文档的 URL 以及版本号。版本号将随新版本软件的发布而进行特定更改。希望 MySQL 的人们能够保留完整的 URL。
http://www.mysql.com/ 至少有一个 URL 长期保持不变。 在本课程中,如果 MySQL 的其它链接被破坏,您应恢复到上述指定的主 MySQL URL,然后从该点搜索软件和文档。
节约时间
如果您在安装数据库服务器软件和准备该软件与 JDBC 一起使用方面是新手,我在本课程中提供的信息,将为您通过文档尝试理解如何下载、安装和连接内容方面节约数天时间。
即使您遇到这些问题,本信息仍将为您节约数据小时时间。
启动和运行
启动和运行 MySQL 以及 JDBC 至少包括以下步骤:
- 下载和安装合适版本的 MySQL 数据库服务器软件(有不同版本可供使用)。
- 下载和安装 MySQL Connector/J -- 用于从 Java 连接到 MySQL 数据库服务器。
- 下载和安装 MySQL 数据库服务器文档。
- 下载和安装 Connector 文档,此文档是数据库服务器文档的单独文档包。
- 编写和测试作为数据库管理员的一个或多个 JDBC 程序,在数据库服务器上创建一个或多个用户,而且在可能情况下创建一个或多个数据库。 (我将向您介绍完成此步骤的三条不同途径。)
- 编写和测试作为用户登录和操作存储在其中一个数据库中数据的 JDBC 程序。
其它 MySQL 软件
最低程度上,您可以从 MySQL 下载各种其它软件包(例如 GUI 管理员软件包)并在计算机上进行安装。
由于本课程的主要目的是使用 JDBC 而非数据库管理功能,我不会对此过多介绍。而是向您介绍如何使用命令行监控程序,它包括于 MySQL 数据库软件中,用于执行满足本课程目标所需的最低限度的数据库管理任务。
文档
我将从讨论可用于 MySQL 数据库服务器和 MySQL Connector/J 的文档开始介绍。
MySQL 数据库服务器文档
您可从 http://dev.mysql.com/doc/ 下载 MySQL 参考指南。 此外,您可从http://dev.mysql.com/doc/mysql/en/Reference.html 获取参考指南的可在线检索版本。
有多种不同格式的可下载版本可供使用,其中包括:
如有足够的磁盘空间,您可将这两种格式的版本下载在本地计算机上。
每章一页格式的指南
在上述列表中,第一种格式包括大量的 HTML 文件。一个 HTML 文件是目录,另外 33 个文件包含参考指南的文本内容。
在速度方面,此格式比第二种格式有一个重要的优势。单击目录中的超级链接和查看浏览器窗口中显示的内容速度相对较快。
但是,此格式有两个缺点。 一个缺点是此格式对于(使用浏览器)搜索整个指南的关键词不是非常有用,因为它被分为大量的单独 HTML 文件。
第二个缺点是,即使 MySQL 4.0 是 2004 年 9 月的推荐版本,但本指南仍包含有关 5.0.1-alpha 版本的信息。 有时,有关较新版本的信息趋向于是有关版本 4.0 的模糊信息。
安装每章一页格式的指南
对于安装此格式的数据库服务器文档,您需要做的工作是下载 zip 文件,并将各种 HTML 文件解压到磁盘中的文件夹。 然后,在浏览器中打开名称为 manual_toc.html 的文件来查看指南。
出于方便起见,我创建了链接目录文件的桌面图标。
全部内容在一个页面上格式的指南
此格式对于(使用浏览器)进行搜索非常有用,因为所有文件均在一个单独的 HTML 文件中。
(实际上有两个 HTML 文件。一个文件包含含有超级链接的目录。第二个文件包含整个指南的文本内容。)
此格式的主要缺点是在于速度,或者由此导致的内容缺失。包含指南文本的 HTML 文件大小大约为四兆字节。在我的计算机上,在浏览器中浏览此指南过程非常缓慢。
本格式的可下载版本还包含有关版本 5.0.1-alpha 的信息,从而导致存在此前所提及的相同缺点。
包括在软件发布中
当您下载和安装当前推荐版本的 MySQL(即版本 4.0.21)时,安装树型结构中的 Docs 文件将包含 all-on-one-page(全部内容在一个页面上)格式的指南副本,它主要是针对版本 4.0.21。 因此,您不需要单独下载此格式。 当下载软件时,您便会获取此格式的指南。
(即使此版本主要针对版本 4.0.21,它仍还包含许多有关更高版本的信息。 除标题页不同之外,它与可以单独下载的版本完全相同。)
安装全部内容在一个页面上格式的指南
如上所述,您不需要做专门针对安装此格式指南的任何事情。 当安装 MySQL 4.0.21 版本的数据库时,将会自动安装此种格式的指南。
(据推测,更高版本的软件还将包含当前此格式指南的副本。)
安装数据库之后,安装树的 Docs 文件夹将包含名称为 manual_toc.html 和 manual.html 的文件。 第一个文件包含含有超级链接的目录,第二个文件包含指南的完整文本。
再次,出于方便起见,我创建了链接目录文件的桌面图标,以便于在我的浏览器中打开。
使用两种格式
由于磁盘有大量空间,我在计算机上同时安装了这两种格式,桌面上有针对每一格式的图标。有时候,当我需要搜索整个文档查找某些内容时,我会打开在单个 HTML 文件中包含完整指南的版本。但是,大多数时间,我会打开和使用多文件版本,因为这种格式的速度更快。
MySQL Connector/J 文档
我在 MySQL 站点未找到单独的可下载版本的连接器文档。 但是,我在 http://dev.mysql.com/doc/connector/j/en/index.html 找到了在线版本。 我可以通过选择 Netscape 7.2 浏览器文件菜单中的页面另存为... 项来本地保存连接器文档。
(出于某种原因,我无法使用 Internet Explorer 6 版本本地保存页面。 但是,此后我还发现,本质上,针对名称为 mysql-connector-java-3.0.15-ga\docs\index.html 的文件中连接器软件的可下载 zip 文件中包含相同的文档。
保存 Netscape 7.2 中的页面导致生成名称为 index.html 的本地文件和名称为 index_files 的相关文件夹。 该文件包含连接器文档的文本。 该文件夹包含样式表和其它相关材料。
连接器文档的安装仅由本地保存此材料和创建链接名称为 index.html 文件的桌面图标组成。
下载 MySQL 数据库服务器
下载页面
截止 2004 年 9 月,数据库服务器和连接器的主下载页面是 http://dev.mysql.com/downloads/。 有希望的是,在 MySQL 发布更高版本的软件时,此 URL 还将保持完好如初。
截止 2004 年 9 月,有多个不同版本的数据库服务器可供下载,其中包括:
由于发布新的数据库服务器版本,此列表预计会随时间而更改。 因此,上述列表中的链接将会过期作废。 当发生这种情况时,您应回到 http://dev.mysql.com/downloads/ 的下载页面,然后下载届时下载最合适您需要的版本。
不同版本的数据库服务器
截止 2004 年 9 月,数据库服务器文档有以下不同版本:
- MySQL 5.0,这是最新的开发版本系列,并且正在积极开发新功能。已发行的 Alpha 版本可允许进行更广泛的测试。
- MySQL 4.1,尚处于 gamma 测试状态,不久将转为生产状态。
- MySQL 4.0,这是当前稳定的(生产质量)版本系列。发行的新版本用于修补漏洞。未增加可降低代码稳定性的新功能。
- MySQL 3.23,这是旧有的稳定(生产质量) 版本系列。此系列已淘汰,因此发行的新版本仅用于修补关键漏洞。
我选择的 MySQL 4.0
我选择下载 MySQL 4.0,因为它是截止 2004 年 9 月具有稳定生产质量的版本。 它导致下载名称为 mysql-4.0.21-win.zip 的发布文件。
(对于未来的 MySQL 数据库服务器版本,发布文件名称可能有所不同。)
安装 MySQL 数据库服务器
安装说明
第 2 节标题为安装 MySQL 的数据库服务器文档中,提供有数据库服务器安装说明。
由于我是在 Windows XP 上进行安装,而且不需要处理源代码,我快速向下跳至第 2.2.1.2 页,标题为安装 Windows 可执行版 。
按我的情况,安装非常简单
由于我未安装较早版本的 MySQL,而且我以管理员身份登录 Windows,因此我需要做的是执行数据库服务器文档的以下说明来在计算机上安装 MySQL 数据库服务器。
- 将发布文件解压到临时目录。
- 运行 setup.exe 程序开始安装过程。如果您要将 MySQL 安装在默认目录(`C:\mysql') 之外的位置,请使用“浏览”按钮指定首选目录。如果您不将 MySQL 安装入默认位置,在启动服务器时需要指定位置。这样做最简便的方法是使用如第 2.2.1.3 页“准备 Windows MySQL 环境”所描述的选项文件。
由于我不想使用选项文件,因此我选择将软件安装在默认目录 C:\mysql。
测试安装
完成安装之后,我执行了第 2.4.1 节标题为 Windows 安装后的流程的数据库服务器文档中所示的一些流程。 尽管我未获取与文档中所示的完全相同的结果,但是结果足以使我相信,我的计算机上已正确安装了 MySQL 数据库服务器。
(未获得完全相同结果的原因在于我未通过管理员权限进行登录。)
不作为 Windows 服务安装
第 2.2.1.7 节标题为作为 Windows 服务启动 MySQL 的数据库服务器文档包含以下内容:
“对于 NT 系列(Windows NT、2000 或 XP),运行 MySQL 的建议方式是将其作为 Windows 服务进行安装。当 Windows 启动和停止时,Windows 自动启动和停止 MySQL 服务器。”
每次启动运行 Windows 时,我不需要启动运行 MySQL 数据库服务器。 每次启动时,我花费足够的时间等待 Windows XP 能够在我的手提电脑上使用。
因此,我未将数据库服务器作为服务进行安装。 在本课程中,我将解释如何在我需要使用它时手动启动和停止数据库服务器。
下载 MySQL Connector/J
什么是 MySQL Connector/J?
对于不了解的人,请让我从解释 MySQL Connector/J 的用途开始。
JDBC API 设计用于使您能够编写单个 Java 程序,用其来操作各种不同 SQL 数据库服务器中的数据,并且无需修改和/或重新编译程序。 为此,您需要:
- 通知 Java 程序数据库服务器的 URL。 您可以通过在启动程序时输入数据来完成此操作。
- 为 Java 程序提供针对您要使用的特定数据库服务器的编程接口。 假设您的计算机上已安装编程接口,您还可以通过在运行程序时输入数据来完成此操作。
编程接口
编程接口处理不同数据库服务器的接口特性。
Sun 将向程序提供此信息的过程称为通过 Java 程序注册数据库服务器。 稍后在本课程中,您会看到如何在示例程序中完成此过程。
连接器下载页面
MySQL Connector/J 的下载页面是 http://dev.mysql.com/downloads/index.html。 截止 2004 年 9 月,从此页可下载以下版本:
正如 MySQL 数据库服务器软件那样,在发布新版本软件时,这些单个链接可能会变得过时。 希望http://dev.mysql.com/downloads/index.html的链接仍保持完整。
MySQL Connector/J 3.0 发布文件
由于我对稳定性非常感兴趣,因此我选择按上述生产版本中确定的那样下载和安装 MySQL Connector/J 3.0。 这将导致下载名称为 mysql-connector-java-3.0.15-ga.zip 的文件。
此 zip 文件在不同文件夹中封装了 194 个单独的文件,包括源代码文件、类文件、pdf 文件、xml 文件、jar 文件、许可证文件、无扩展名的文件、清单文件、HTML 文件以及此处未列出的其它文件类型。
zip 文件还在名称为 testsuite 的文件夹中包含多个 java 程序,该程序可用于测试您的安装。 您会发现它们对于该用途非常有用。 此外,这些程序展示了各种使用 JDBC 的数据库操作,因此,您会发现它们象示例程序那样非常有用。
幸运的是,正如我在下面解释的那样,在安装连接器软件时,可以忽略除一个之外的所有这些文件。
安装 MySQL Connector/J
一般安装说明
标题为设置 CLASSPATH (供单独使用)的连接器文档第 2.2.1 节中显示以下语句。
“取消缓存发布缓冲文档之后,您可以按以下两种方法之一安装驱动程序:将 "com" 和 "org" 子目录及其所有内容复制到您喜欢的任何地方,然后使类路径中的目录包含 "com" 和 "org" 子目录,或者将 mysql-connector-java-[version]-bin.jar 置于类路径中,这可以通过将其 FULL 路径添加到 CLASSPATH 环境变量,或者通过将 .jar 文件复制到 $JAVA_HOME/jre/lib/ext 来完成。”
我的安装
实际上,上述引述描述了三种选项而非两种选项。 长话短说,我选择了第三个选项。 我解压了压缩文件中名称为 mysql-connector-java-3.0.15-ga-bin.jar 的 jar 文件,然后将其复制到名称为 c:\j2sdk1.4.2\jre\lib\ext 的文件夹,该文件夹是当前在我的计算机上安装的 Java 版本的安装目录树。
按这种方法做的优点是我不需要修改类路径环境变量。缺点是下次我升级到新版本 Java 时,我必须记住保存 MySQL 连接器 jar 文件,然后将其复制到我的新 Java 安装的目录树。
您的安装
如果您首选第一个选项,则连接器文档包含的大量信息可帮助您执行修改类路径所需的步骤。
测试安装
我未使用上述名称为 testsuite 的文件夹中所提及的任何测试程序。 而是使用我早前使用不同 SQL 数据库服务器开发的 JDBC 程序测试我的安装。
您可以使用此前提及的 testsuite 文件夹中的测试程序测试您的安装。 另外,稍后我将在本课程中提供和解释可用于测试安装的 JDBC 程序示例。 但是,在您可以测试安装之前,您必须开始运行 MySQL 数据库服务器。
启动数据库服务器
此时,您的计算机上应已安装在 JDBC 程序中使用数据库服务器所需的所有软件,以便供您使用。下一步是确认您可以开始运行数据库服务器。
选择 Windows 服务器
我发现,有必要结合数据库服务器文档的一些信息来确定从命令行启动服务器的最佳方法。 例如,您可以在第 2.2.1.4 节标题为选择 Windows 服务器的数据库服务器文档中找到下表。
| 二进制 |
说明 |
| mysqld |
通过完整调试以及自动内存分配检查进行编译、符号链接以及 InnoDB 和 BDB 表。 |
| mysqld-opt |
优化的二进制。从版本 4.0 开始启用 InnoDB。版本 4.0 之前,此服务器不包括交易表格支持。 |
| mysqld-nt |
为 Windows NT、2000 和 XP 而优化的二进制,并且支持命名管道。 |
| mysqld-max |
优化的二进制,支持符号链接以及 InnoDB 和 BDB 表格。 |
| mysqld-max-nt |
比如 mysqld-max,但通过支持命名管道进行编译。 |
解释不同类型的服务器
下面是对表格内容的解释:
“我们发现,具有最普通名称 (mysqld) 的服务器,是许多用户最可能默认选择的服务器。但是,也正是由于此服务器包含完整的调试支持功能,导致最高的内存和 CPU 占用。如果您不需要调试支持,并且不需要由 -max 服务器提供的最大功能集,或者由 -nt 服务器提供的命名管道支持,则名称为 mysqld-opt 的服务器是更较为常用的服务器。”
MySQL 4.1.2 中的更改
另一解释表明,从 MySQL 4.1.2 开始,服务器名称已进行更改,排除服务器名称 mysqld-opt 并用 mysqld-debug 替换调试版本 (mysqld)。 因此,如果您安装的是 MySQL 4.1.2 或更高版本,您应使用语法 mysqld 而非 mysqld-opt 从优化的二进制文件开始运行服务器。
启动 MySQL 4.0.21
由于我运行的是 MySQL 4.0.21 而且需要确保我所作内容与大量学生的不同操作系统相兼容,我推断我应使用语法 mysqld-opt 来开始运行服务器。
第 2.2.1.5 节标题为首次启动服务器的数据库服务器文档指明,在命令提示符处应使用以下命令来开始运行服务器:
C:\mysql\bin\mysqld --console
正如我理解的那样,--console 的用途是使错误消息显示在标准错误设备(通常是屏幕)上,而非输入错误日志文件。 这正是我希望发生的。
结合以上给出的两段信息,我推断我应在命令提示符处输入以下命令来启动 MySQL 数据库服务器:
C:\mysql\bin\mysqld-opt --console
封装在批处理文件中
因此,我创建了名称为 MySqlStart.bat 的批处理文件,并且出于方便起见,将该文件链接到桌面上的图标。 批处理文件包含清单 1 中所示的两个命令,在课程结束时,请在清单 30 中重复这两个命令。
C:\mysql\bin\mysqld-opt --console
pause
Listing 1 Contents of MySqlStart.bat
|
启动屏幕输出
图 1 显示执行名称为 MySqlStart.bat 的批处理文件之后的屏幕输出。
(注意,对我来说,有必要手动输入一行单词,以便使屏幕输出与此较窄的出版格式相适合。)
C:\mysql>C:\mysql\bin\mysqld-opt --console
040918 13:59:47 InnoDB:Started
C:\mysql\bin\mysqld-opt:ready for connections.
Version:'4.0.21' socket: ''
port:3306 Source distribution
图 1 MySQL 数据库服务器启动序列
|
在停止服务器之前,图 1 中所示的流程窗口仍然保持打开和活动。 在此期间,可以使用 JDBC 连接到服务器。
停止数据库服务器
这可能是在关闭计算机之前关闭服务器的好主意。 第 2.2.1.6 节标题为从 Windows 命令行启动 MySQL 的数据库服务器文档规定您可以执行以下命令来停止 MySQL 服务器:
C:\mysql\bin\mysqladmin -u root shutdown
因此,我创建了名称为 MySqlStop.bat 的批处理文件,并且出于方便起见,将该文件链接到桌面上的图标。批处理文件包含清单 2 中所示的两个命令,在课程结束时,请在清单 31 中重复这两个命令。
C:\mysql\bin\mysqladmin -u root shutdown
pause
清单 2 MySqlStop.bat 的内容
|
服务器关闭时的屏幕输出
图 2 显示的是执行名称为 MySqlStop.bat 的文件时服务器流程窗口中的屏幕输出。
040918 14:00:02 C:\mysql\bin\mysqld-opt:
Normal shutdown
040918 14:00:03 InnoDB:Starting shutdown...
040918 14:00:05 InnoDB:Shutdown completed
040918 14:00:05 C:\mysql\bin\mysqld-opt:
Shutdown Complete
C:\mysql>pause
Press any key to continue . . .
图 2 停止 MySQL 服务器时的
屏幕输出。
|
(如前一样,对我来说,有必要在图 2 中手动输入一行单词,以便使屏幕输出与此较窄的出版格式相适合。)
在服务器关闭之后,试图从 JDBC 连接到服务器将失败。
使用监控程序创建新数据库
现在,您知道了如何启动 MySQL 数据库服务器,接下来将了解如何:
- 创建可以使用 JDBC 在 Java 程序中操作的数据库。
- 创建拥有使用 JDBC 在 Java 程序中操作数据库的必要权限的新用户。
不同的方法
下面我将介绍完成此操作的三种不同方法:
- 在运行时与手动数据输入耦合的、名称为 mysql 的命令行。 (出于以后自我明白原因,我将此称为监控程序。)
- 使用源自文本文件、与数据输入耦合的监控程序。
- 在 Java 程序中使用 JDBC。
在本节和后面标题为使用监控程序创建新用户的章节中,我将举例说明第一种方法。
我将在标题为使用文本文件管理数据库服务器的章节中举例说明第二种方法。
我将在标题为讨论和示例代码的章节中举例说明第三种方法,该节介绍了如何使用 JDBC 管理和操作数据库服务器。
监控程序和手动数据输入
监控程序名称为 mysql.exe。 它位于 c:\mysql\bin 中。 使程序使登录数据库服务器和在命令行输入命令成为可能:
- 创建数据库
- 添加新用户
- 修改数据库
- 执行 ad-hoc 查询等
(除非您真正享受键入,否则监控程序使用起来不会有很多乐趣。)
要真正了解 MySQL ...
为了真正了解如何使用 MySQL,您需要详细学习 MySQL 数据库服务器文档以及一些不错的 SQL 书籍。
本课程的目的是教您掌握充足的入门知识。完成本课程之后,您应能够成功地编写和执行能够在 MySQL 数据库服务器上操作数据库表的简单 JDBC 程序。
默认的管理用户
正如我理解的那样,当首次安装 MySQL 数据库服务器时,将有一个名称为 root 的默认用户具有完全管理权限,并且不需要密码。此时,服务器是完全开放的,并且不安全。
(对于您应如何增加服务器的安全,服务器文档提供了各种建议。)
名称为 root 的用户可以创建新数据库和创建新用户,并且在数据库中注册这些用户。
MySQL 安装时的现有数据库
另外,正如我理解的那样,当首次安装时,服务器上有两个现有的数据库。 名称为 test 的数据库是开放的,不需要密码。 任何用户都可以访问此数据库。
还有一个名称为 mysql 的数据库,显然是用于跟踪数据库等。 我认为,只有具有管理权限的用户才可访问此数据库。
使用监控程序添加新数据库
使用监控程序添加新数据库的第一步是以名称为 root 的管理用户身份登录数据库服务器并访问名称为 mysql 的数据库。 在为 root 用户分配密码之后,可以在命令提示符处输入以下命令完成登录:
c:\mysql\bin\mysql --user=root mysql
(在显示不清楚情况下,word 用户前面应有两个减号字符。)
屏幕输出
假设 MySQL 数据库服务器正在运行,通过输入此命令生成的屏幕输出如图 3 所示。
(注意,在图 3 中,以及随后的几张图中,对我而言,需要手动在屏幕输出中输入一行单词,以便使材料能够适合此较窄的出版格式。)
C:\jnk>c:\mysql\bin\mysql --user=root mysql
Welcome to the MySQL monitor.Commands end with ;
or \g.
Your MySQL connection id is 26 to server version:
4.0.21
Type 'help;' or '\h' for help.Type '\c' to clear
the buffer.
mysql>
图 3 监控管理员登录输出
|
监控程序
注意,此程序称为 MySQL 监控程序。 这解释了我为何将其称为监视器或监控程序的原因。
此程序的目的是使您能够从键盘输入 SQL 数据库命令。特别是,在图 3 结束处以粗体显示的提示符读作:
mysql>
这不是一个命令行提示符,通常看起来象是:
C:\jnk>
而是在监控程序请求用户输入时程序生成的提示符。
SQL 命令端子
如图 3 中所示的那样,SQL 命令以分号字符或 \g 结尾(请注意本文本中字符 g 的字体与图 3 中所示字体的差别)。
SQL 命令通常非常长。您可以在连续的程序提示符处输入连续的 SQL 命令部分。
(稍后,您会看到监控程序使用不同的连续提示符语法。)
直至您输入分号字符或 \g,该程序才响应并尝试执行完整的 SQL 命令。
终止监控程序
您可以通过在命令提示符处输入 \q 来终止监控程序。
(注意,这是 quit 中的 q 而非 good 中的 g。)
创建名称为 JunkDB 的新数据库
图 4 显示的是名称为 root 的用户使用监控程序创建名称为 JunkDB 的数据库然后终止监控程序的屏幕输出。
C:\jnk>c:\mysql\bin\mysql --user=root mysql
Welcome to the MySQL monitor.Commands end with ;
or \g.
Your MySQL connection id is 27 to server version:
4.0.21
Type 'help;' or '\h' for help.Type '\c' to clear
the buffer.
mysql> CREATE DATABASE JunkDB;
Query OK, 1 row affected (0.13 sec)
mysql> \q
Bye
C:\jnk>
图 4 创建名称为 JunkDB 的数据库
|
图 4 中的新材料在图中底半部分以黑粗体显示。图 4 上半部分中的材料是图 3 中所示材料的重复。
使用批处理文件和文本文件
稍后,我将向您介绍如何使用 Windows 批处理文件和相关文本文件创建新数据库。 稍后,我将向您介绍如何使用 Java JDBC 程序创建新数据库。
图 5 显示的是名称为 root 的用户使用监控程序添加名称为 auser的新用户的屏幕输出。
新材料在图的下半部分以黑粗体字显示。
C:\jnk>c:\mysql\bin\mysql --user=root mysql
Welcome to the MySQL monitor.Commands end with ;
or \g.
Your MySQL connection id is 30 to server version:
4.0.21
Type 'help;' or '\h' for help.Type '\c' to clear
the buffer.
mysql> GRANT SELECT,INSERT,UPDATE,
-> DELETE,CREATE,DROP
-> ON JunkDB.*
-> TO 'auser'@'localhost'
-> IDENTIFIED BY 'drowssap';
Query OK, 0 rows affected (0.01 sec)
mysql> \q
Bye
C:\jnk>
图 5 添加名称为 auser 的新用户。
|
较长的 SQL 命令
此 SQL 命令比用于创建新数据库的命令长很多。 此命令需要填写数个连续行才能防止它超出屏幕宽度。
(请注意新程序提示符和连续程序提示符语法中存在的差别。看似箭头的提示符是连续提示符。)
在此我不想详细解释 SQL 命令。 出于该目的,我将仅建议您参考 MySQL 数据库文档和一本不错的 SQL 书籍。 但是,SQL 命令是相对自明的。
SQL 命令的含义
此 SQL 命令授予名称为 auser 的从 localhost 访问数据库的用户六个针对名称为 JunkDB 的数据库的不同权限。
(授予同一用户从不同机器访问网络的权限需要不同的语法。)
名称为 auser 的用户将被允许使用密码 drowssap 访问名称为 JunkDB 的数据库,(这是一个反向拼写的密码,以便使我易于牢记)。
正如以前提及的那样,除非您真正享受输入,在手动数据输入模式下使用监控程序不是使用数据库的有趣方式。例如,如果您输入错误,则必须返回并从开始重新键入完整命令。
幸运的是,有一种更好的方法。该方法是使用文本文件向监控程序提供命令。然后,如果出现错误,您可以简单地编辑文本文件,然后重新运行程序。
如何发挥作用?
长话短说,您可以通过重新定向输入,从而从文本文件而非从键盘来进行输入,来启动监控程序。 第 3.5 节标题为在批处理模式下使用 mysql 的数据库服务器文档中描述了此过程。
创建新数据库
设置此过程可能有多种方式。 我选择使用批处理文件和文本文件的组合。 批处理文件启动监控程序,以 root 身份登录,然后将输入重新定向至相关的文本文件。
例如,用于创建名称为 JunkDB 的新数据库的文件显示于课程将近结束时的清单 32 和清单 33 中。
创建新用户
用于创建名称为 auser 的新用户的文件显示于清单 34 和清单 35 中。
将这两个文件的内容与图 5 中所示的手动数据输入相比较。 新用户被授予从 localhost 通过密码 drowssap 访问名称为 JunkDB 数据库的六个不同权限。
删除名称为 auser 的用户
用于删除名称为 auser 用户的文件显示于清单 36 和清单 37 中。 调用用户权限和删除用户的流程在数据库服务器文档第 14.5.1.1 节标题为 DROP USER Syntax 的文档将近结束地方进行了解释。
删除名称为 JunkDB 的数据库
用于删除名称为 JunkDB 的数据库的文件显示于清单 38 和清单 39 中。 第 14.2.8 节标题为 DROP DATABASE Syntax. 的数据库服务器文档中解释了删除数据库的流程。
JDBC 程序讨论和示例代码
在上述所有工作准备就绪情况下,现在可以了解如何编写 JDBC 程序来管理和操作 MySQL 数据库服务器上的数据。
三个单独的程序
我将解释这三个程序。第一个程序名称为 Jdbc11,显示如何:
- 以名称为 root 的管理员身份登录服务器。
- 创建名称为 JunkDB 的新数据库。
- 在名称为 JunkDB 的数据库中注册名称为 auser 的新用户,该用户具有六个不同权限,密码为 drowssap。
第二个程序名称为 Jdbc12,显示如何:
- 以名称为 root 的管理员身份登录服务器。
- 调用权限并删除名称为 auser 的用户。
- 删除名称为 JunkDB 的数据库。
第三个程序名称为 Jdbc10,显示了如何以名称为 auser 的用户登录服务器,并且以多种方式操作名称为 JunkDB 的数据库。
我将把这些程序分为数个片段并对这些片段进行讨论。所有程序的完整清单显示于课程将近结束时的清单 40、41 和 42 中。
Jdbc11 - 创建数据库和新用户
名称为 Jdbc11 的程序的用途是以名称为 root 的默认管理员身份登录名称为 mysql 的主数据库,该名称的密码为空白,以便对 MySQL 数据库服务器执行以下更新:
- 创建名称为 JunkDB 的新数据库。
- 创建名称为 auser 的新用户,用户密码为 drowssap,有六个针对名称为 JunkDB 的数据库的不同权限。
输出或缺少
这两项操作可以生成不可见的输出。但是,当不成功时,这两项操作会在输出中生成错误消息。
(但是,请注意,程序中的该打印语句会生成一系列独立于对数据库服务器所执行操作的数行输出。)
服务器必须运行
在启动此程序之前,MySQL 服务器必须在 localhost 上运行。 之前我提供了启动和停止数据库服务器的说明(参见图 1 的清单 1 和图 2 的清单 2)。
在 WinXP、MySQL 版本 4.0.21-win 以及 JDBC 连接器版本 mysql-connector-java-3.0.15-ga 下,使用 Java SDK 1.4.2 测试程序。
使用 JDBC 的关键步骤
使用 JDBC 操作数据库有五个关键步骤:
- 为您要使用的数据库服务器加载和注册 JDBC 驱动程序类(编程接口)。
- 获取表示与数据库服务器连接的 Connection 对象(模拟登录服务器)。
- 获取一个或多个用于在操作数据库中使用的 Statement 对象。
- 使用 Statement 对象操作数据库。
- 关闭与数据库的连接。
我将在下面的示例程序讨论中重点介绍这五个步骤。
Jdbc11 类定义的开头
名称为 Jdbc11 的程序的第一个程序片段显示于清单 3 中。 完整程序显示于课程将近结束时的清单 40 中。
public class Jdbc11 {
public static void main(String args[]){
System.out.println(
"Copyright 2004, R.G.Baldwin");
try {
Statement stmt;
清单 3
|
清单 3 中的代码简明易懂,显示了类的开头、main 方法的开头以及打印语句。
清单 3 还表明了 Statement 类的本地变量。 我将在稍后更多地介绍 Statement 接口。
为 MySQL 注册 JDBC 驱动程序
清单 4 显示的是执行此前所列示的第一个关键步骤的语句(加载和注册 JDBC 驱动程序类)。 此语句通过 Java 程序注册 MySQL 驱动程序类,使此程序有可能操作 MySQL 服务器上的数据。
Class.forName("com.mysql.jdbc.Driver");
清单 4
|
驱动程序类参考
标题为设置 CLASSPATH (供单独使用)的 MySQL 连接器文档第 2.2.1 节中显示以下语句。
“如果您准备将驱动程序与 JDBC DriverManager 一起使用,您应使用 "com.mysql.jdbc.Driver" 作为执行 java.sql.Driver 的类。”
在第 2.2.2.节 标题为驱动程序类名称和 JDBC URL 格式的连接器文档中同样提供有此信息。
驱动程序接口
请注意上述引文中驱动程序接口的参考。 下面是 Sun 对驱动程序接口的一些观点:
"每一个驱动程序类必须实现的接口。
Java SQL 框架允许多个数据库驱动程序。
每一驱动程序应提供实现驱动程序接口的类。
DriverManager 将尝试加载它可以发现的许多驱动程序,然后对于任何指定的连接请求,它将轮流询问每一驱动程序,以便尝试连接到目标 URL。...
加载驱动程序类时,它将创建一个自身的实例,并通过 DriverManager 进行注册。这意味着用户可以通过调用
Class.forName("foo.bah.Driver") 加载和注册驱动程序”
驱动程序类的名称
为了使用 JDBC 程序连接特定的数据库服务器,您必须从驱动程序供应商(或者从支持该数据库服务器的某一第三方)获取此关键驱动程序类的名称。 然后,您必须将程序加载到类。
这是将连接器软件包中的其它类连接到 Java 程序的类。没有这个类,Java 程序将无法与数据库服务器成功通信。
加载驱动程序类
清单 4 中的语句将导致按上面所引用的 Sun 文档中的描述加载此类。
(如果您对使用名称为 Class 的类的 forName 方法不熟悉,请参阅The Essence of OOP using Java:Static Members 获取为名称为 Class 的类的简要介绍。 然后打开您的 Google 搜索引擎,将搜索结果数设为 100,搜索所有关键词 java forname richard baldwin。 这将把您指向我已在讨论本主题中所发布的前面几个课程。 如果未找到您需要的内容,请单击 Google 最后一页底部的链接,即 repeat the search with the omitted results included,查看更多课程。
将驱动程序类指定为字符串
注册驱动程序类有多个备用方法,清单 4 中仅显示了其中一个方法。 清单 4 中的语句使得有可能将驱动程序指定为字符串。 此方法的主要优势是可以在运行时通过多种方法由程序获取此字符串。
尽管该字符串以硬代码的形式嵌入这个不作为一项要求的简单程序。对于要与两个或更多数据库服务器一起使用的更常规程序,此字符串将最可能作为某种形式的用户输入来提供。
数据库服务器的 URL
MySQL 和其它类似的数据库引擎作用如同网络上的服务器。它们可以由 URL 确定为其它类型的服务器(例如 HTTP 服务器和 FTP 服务器)。下一片段定义的是我在本示例程序中使用的 MySQL 数据库服务器的 URL。
清单 5 中的代码定义了驻留在 localhost 和服务于默认端口号 3306 的 MySQL 数据库服务器上名称为 mysql的主数据库的 URL。
(我已从 URL 省略默认端口号,但我决定包括该端口号,以便提醒我注意。 Note that the "//" characters shown to the right of "mysql:"form part of the URL.They are not comment indicators.)
String url =
"jdbc:mysql://localhost:3306/mysql";
清单 5
|
第 2.2.2.节 标题为驱动程序类名称和 JDBC URL 格式的连接器文档中提供了 URL 格式。 URL 格式包含多个可选元素。 清单 6 中的语句将引用此 URL,以用于获取数据库连接之目的。
获取数据库连接
清单 6 中的代码执行此前所示的第二个关键步骤(获取连接对象)。
清单 6 获取在指定 URL (mysql on localhost port 3306) 的数据库连接,用户名称为 root,密码为空。 正如您已知道的那样,此用户是具有完全权限的默认管理员,包括创建数据库和在这些数据库上注册新用户。
Connection con =
DriverManager.getConnection(
url,"root", "");
清单 6
|
实际上,清单 6 将使 JDBC 程序登录 MySQL 数据库服务器,所采用的方式是模拟图 3、图 4 和图 5 中的第一行以及清单 32、清单 34、清单 36 和清单 38 中所示的批处理文件中的语句。
getConnection 方法
getConnection方法是 DriverManager类的一种静态方法。当调用 getConnection 时,DriverManager将尝试查找在初始化时以及使用与当前 applet 或应用程序相同的类加载程序明确加载的合适驱动程序。
有多个过载版本的 getConnection 方法。 清单 6 中所使用的版本试图与针对具有特定密码的特定用户的指定数据库 URL 建立连接。
如果试图获取与数据库服务器的连接成功,则该方法返回 Connection 类型的对象。在此程序中,Connection 对象的参考存储在名称为 con 的参考变量中。
如果尝试不成功,将会抛出一个异常的 SQLException 类型。 与问题本质相关的信息将封装在 SQLException 对象中。
正如您稍后看到的那样,在连接上下文中执行 SQL 语句并返回结果。
显示某些信息
清单 7 中的代码不是程序的关键代码。此代码只显示有关 URL 和连接的信息。
System.out.println("URL:" + url);
System.out.println("Connection:" + con);
清单 7
|
获取语句对象
清单 8 中的代码执行此前所列的第三个关键步骤 (获取一个或多个语句对象。)
此代码调用连接接口的 createStatement 方法,以获取语句类型的对象。
stmt = con.createStatement();
清单 8
|
重新调用该 con 是连接类型对象的参考。 连接对象定义与特定数据库的连接(会话)。 在连接上下文中执行 SQL 语句并返回结果。
根据 Sun,语句对象是:
"... 用于执行静态 SQL 语句并返回它生成的结果。"
返回的结果
结果(如有)是以 ResultSet对象的形式返回。 我将在以后结合讨论名称为 Jdbc10 的程序,更深入地介绍 ResultSet 接口。
(此程序中使用的 SQL 命令不返回任何结果。)
语句接口的方法
语句接口声明了许多可用于访问数据库服务器和操作数据库中数据的方法。其中一种方法是 executeUpdate,该方法将在此程序中使用。
executeUpdate 方法具有一个单独的字符串参数。 此参数必须是有效的 SQL 命令。该方法用于执行 SQL INSERT、UPDATE 或 DELETE 语句。此外,可以使用此方法执行不返回任何结果的 SQL 语句。
创建新数据库
清单 9 中的代码执行此前所提供的列表中的第四个关键步骤(使用 Statement 对象操作数据库).
清单 9 调用 Statement 对象的 executeUpdate 方法创建名称为 JunkDB 的新数据库。
stmt.executeUpdate(
"CREATE DATABASE JunkDB");
清单 9
|
executeUpdate 方法
Sun 认为 executeUpdate 方法:
"公共 int executeUpdate(String sql) 抛出 SQLException
执行指定的 SQL 语句, ...
参数:sql - SQL INSERT、UPDATE 或 DELETE 语句或 SQL 语句,不返回结果
返回:INSERT、UPDATE 或 DELETE 语句的行数,或者为不返回结果的 SQL 语句返回 0。"
方法参数是 SQL 命令
请注意清单 9 中的方法与图 4 中所示的交互输入以及清单 33 中所示的文本文件内容的相似度。
在所有三种情况下,在数据库中调用 SQL 命令,以创建名称为 JunkDB 的新用户。 此 SQL 命令不返回结果,因此它适合与上述 executeUpdate 方法一起使用。
在所有三种情况下,SQL 命令由能够创建新数据库的名称为 root 的默认管理员调用。
创建新用户
清单 10 中的代码执行此前所提供的列表中的第四个关键步骤(使用 Statement 对象操作数据库).
清单 10 中的代码再次调用 executeUpdate 方法,创建名称为从 auser 的新用户,该用户能够从 localhost 访问名称为 JunkDB 的数据库,所使用的密码为 drowssap,并且具有六个不同的权限。
stmt.executeUpdate(
"GRANT SELECT,INSERT,UPDATE,DELETE," +
"CREATE,DROP " +
"ON JunkDB.* TO 'auser'@'localhost' " +
"IDENTIFIED BY 'drowssap';");
清单 10
|
另一 SQL 命令
请再次注意清单 10 中的 executeUpdate 方法参数与图 5 中所示的交互输入以及清单 35 中所示的文本文件内容的相似度。
图 5、清单 10 和清单 35 举例说明了名称为 root 的默认管理员调用数据库服务器上的相同 SQL 命令的三种不同方法。
关闭连接和终止程序
清单 11 执行此前所列的第五个关键步骤,即关闭连接和终止程序。
con.close();
}catch( Exception e ) {
e.printStackTrace();
}//end catch
}//end main
}//end class Jdbc11
清单 11
|
运行名称为 Jdbc11 的程序的结果
在成功运行此程序之后,MySQL 数据库服务器包含名称为 JunkDB 的数据库以及名称为 auser 的用户,它们具有有密码为 drowssap 的数据库有关的各种权限。
此时,名称为 auser 的用户有可能执行 JDBC 程序,该用户操作名称为 JunkDB 的数据库的内容。 这将是名称为 Jdbc10 程序的用途,我将在稍后进行解释。
但是,首先,我将向介绍如何编写 JDBC 程序来删除名称为 auser 的用户和从 MySQL 数据库服务器删除名称为 JunkDB 的数据库。
JDBC12 - 删除用户和删除数据库
名称为 Jdbc11 的程序的用途是以名称为 root 的默认管理员身份登录名称为 mysql 的主数据库,该名称的密码为空白,以便对 MySQL 数据库服务器执行以下更新:
- 调用权限并删除名称为 auser 的用户。
- 删除名称为 JunkDB 的数据库。
输出
这两项操作可以生成不可见的输出。但是,当不成功时,这两项操作会在输出中生成错误消息。
(程序中的打印语句生成与上述所列操作不相关的输出。)
反转
此程序是此前所讨论的名称为 Jdbc11 程序的反转,它可以创建名称为 JunkDB 的数据库和在数据库上注册名称为 auser 的用户。
服务器必须运行
在启动此程序之前,MySQL 服务器必须在 localhost 上运行。 之前我提供了启动和停止数据库服务器的说明(参见图 1 的清单 1 和图 2 的清单 2)。
测试
在 WinXP、MySQL 版本 4.0.21-win 以及 JDBC 连接器版本 mysql-connector-java-3.0.15-ga 下,使用 Java SDK 1.4.2 测试程序。
Jdbc12 类的开头
清单 12 显示的是类定义的开头以及名称为 Jdbc12 程序的 main 方法的开头。 清单 41 中提供了完整的程序清单。
清单 12 中的代码与所讨论的名称为 Jdbc11 的程序的代码相同,因此,我不再重复进行讨论。
public class Jdbc12 {
public static void main(String args[]){
System.out.println(
"Copyright 2004, R.G.Baldwin");
try {
Statement stmt;
//Register the JDBC driver for MySQL.
Class.forName("com.mysql.jdbc.Driver");
//Define URL of database server for
// database named mysql on the localhost
// with the default port number 3306.
String url =
"jdbc:mysql://localhost:3306/mysql";
//Get a connection to the database for a
// user named root with a blank password.
// This user is the default administrator
// having full privileges to do anything.
Connection con =
DriverManager.getConnection(
url,"root", "");
//Display URL and connection information
System.out.println("URL:" + url);
System.out.println("Connection:" + con);
//Get a Statement object
stmt = con.createStatement();
清单 12
|
调用权限和删除名称为 auser 的用户
清单 13 连续调用 executeUpdate 方法四次,使数据库服务器能够调用权限并删除名称为 auser 的用户。 清单 36 和 37 中此前讨论并举例说明了完成此任务所需的 SQL 命令。
stmt.executeUpdate(
"REVOKE ALL PRIVILEGES ON *.* " +
"FROM 'auser'@'localhost'");
stmt.executeUpdate(
"REVOKE GRANT OPTION ON *.* " +
"FROM 'auser'@'localhost'");
stmt.executeUpdate(
"DELETE FROM mysql.user WHERE " +
"User='auser' and Host='localhost'");
stmt.executeUpdate("FLUSH PRIVILEGES");
清单 13
|
删除名称为 JunkDB 的数据库
清单 14 调用 executeUpdate 方法删除名称为 JunkDB 的数据库,使用清单 38 和 39 中此前讨论和举行说明的 SQL 命令。
stmt.executeUpdate(
"DROP DATABASE JunkDB");
清单 14
|
关闭连接和终止程序
清单 15 关闭连接和终止程序。
con.close();
}catch( Exception e ) {
e.printStackTrace();
}//end catch
}//end main
}//end class Jdbc12
清单 15
|
Jdbc10 - 操作数据库中的数据
前面这两个程序的属性本质上是管理数据库服务器。特别是,添加和删除数据库以及数据库服务器用户的那些程序。
用户前景
名称为 Jdbc10 的程序的用途是举例说明如何使用 JDBC 访问 localhost 上的 MySQL 数据库服务器和操作存储在该数据库中的数据。
服务器必须运行
在启动名称为Jdbc10的程序之前,MySQL 服务器必须在 localhost 上运行。 之前我提供了启动和停止数据库服务器的说明(参见图 1 的清单 1 和图 2 的清单 2)。
服务器必须准备就绪
此外,在启动此程序之后,必须已在服务器上创建名称为 JunkDB 的数据库,而且必须在数据库上注册名称为 auser 的用户,用户密码为 drowssap。
名称为 auser 的用户必须具有能够在数据库中创建表格和将数据插入表格的权限。 此外,必须允许用户在数据库中执行对表格的 SELECT 查询。
创建数据库和添加用户
创建数据库和添加用户至少有三种方法:
- 如图 4 和图 5 所示,通过监控程序执行手动数据输入。
- 如清单 32、33、34 和 35 中所示,使用与从文本文件的数据输入耦合的监控程序。
- 运行此前所讨论的名称为 Jdbc11 的程序。
Jdbc10 程序的属性
此程序:
- 以 auser 身份登录,密码为 drowssap。
- 访问名称为 JunkDB 的数据库。
- 创建名称为 myTable 的表格。
- 将五行数据输入名称为 myTable 的表格中。
- 访问名称为 myTable 表格中的数据。
- 显示数据。
- 删除名称为 myTable 的表格。
显示表格的内容可以使用两种不同的方法。第一种方法是显示表格中的所有数据。第二种方法是只显示表格特定行中的数据。
注意事项
作为注意事项,在尝试创建新表格前,程序会尝试删除具有相同名称的表格。如果具有相同名称的表格已存在,则将其删除。
如果尝试删除表格时此表格不存在,则出抛出异常。这种异常可以捕获、显示和忽略。
程序输出
在正常情况下,此程序可生成如图 6 所示的输出,在这种情况下,当启动程序时,名称为 myTable 的表格不存在(有关连接对象的特性会有所变化)。
Copyright 2004, R.G.Baldwin
URL:jdbc:mysql://localhost:3306/JunkDB
Connection:com.mysql.jdbc.Connection@1430b5c
java.sql.SQLException:Base table or view not
found message from server:"Unknown table
'mytable'"No existing table to delete
Display all results:
test_id= 1 str = One
test_id= 2 str = Two
test_id= 3 str = Three
test_id= 4 str = Four
test_id= 5 str = Five
Display row number 2:
test_id= 2 str = Two
图 6
|
测试
在 WinXP、MySQL 版本 4.0.21-win 以及 JDBC 连接器版本 mysql-connector-java-3.0.15-ga 下,使用 Java SDK 1.4.2 测试程序。
类定义的开头
类定义在清单 16 中开头。在课程将近结束的清单 42 中显示了完整的程序清单。
public class Jdbc11 {
public static void main(String args[]){
System.out.println(
"Copyright 2004, R.G.Baldwin");
try {
Statement stmt;
ResultSet rs;
//Register the JDBC driver for MySQL.
Class.forName("com.mysql.jdbc.Driver");
清单 16
|
除了 ResultSet 类型的变量之外,清单 16 中的代码与前两个程序中的代码相同。 我将在以后深入介绍 ResultSet 类型。
定义数据库 URL
清单 17 定义了数据库服务器的 URL 以及以后由本程序访问的数据库。
String url =
"jdbc:mysql://localhost:3306/JunkDB";
清单 17
|
请注意,前两个程序访问了名称为 mysql 的主数据库,而此程序访问名称为 JunkDB 的用户数据库。 否则,清单 17 中的代码将与前一程序中的代码相同。
获取数据库连接
清单 18 获取数据库连接
Connection con =
DriverManager.getConnection(
url,"auser", "drowssap");
清单 18
|
调用清单 18 中的代码与使用特定密码登录特定数据库的特定用户相似。
前两个程序获取与名称为 mysql 的主数据库的连接,默认用户名为 root,密码为空白。
此程序获取与名称为 JunkDB 的数据库的连接,用户名为 auser,密码为 drowssap。
显示某些信息并获取语句对象
正如在前两个程序中那样,清单 19 显示有关 URL 和连接的一些信息,然后获取 Statement 对象。
//Display URL and connection information
System.out.println("URL:" + url);
System.out.println("Connection:" + con);
//Get a Statement object
stmt = con.createStatement();
清单 19
|
删除名称为 myTable 的表格(如果存在)
出于某些原因,例如前面运行的此程序尚未结束,名称为 myTable 的表格可能存在于名称为 JunkDB 的数据库中。 如果表格已存在,将不能创建具有该名称的新空白表格。 此程序的要求是创建名称为 myTable 的特定格式的空白表格。
因此,作为注意事项,在尝试创建新表格前,清单 20 中的代码尝试删除名称为 myTable 的表格。 如果具有该名称的表格已存在,则删除该表格。
如果尝试删除表格时此表格不存在,则出抛出异常。这种异常可以简单地捕获、显示和忽略。
try {
stmt.executeUpdate("DROP TABLE myTable");
}catch( Exception e ) {
System.out.print(e);
System.out.println(
"No existing table to delete");
}//end catch
清单 20
|
清单 20 中的代码调 executeUpdate 方法,这种方法您已熟悉。 只有作为参数向方法提供的 SQL 命令语法对此程序来说是新的。
创建名称为 myTable 的新表格
清单 22 中的代码调用 executeUpdate 方法创建名称为 myTable的新表格。 为了全面理解作为参数传递给方法的 SQL 命令,我将向您建议阅读 SQL 书籍。
stmt.executeUpdate(
"CREATE TABLE myTable(test_id int," +
"test_val char(15) not null)");
清单 22
|
简单地说,新表格有两个栏。 第一栏名称为 test_id,而且将指定包含整数数据。
第二栏将命名为 test_val,而且将指定包含长达 15 个字符 (在 Java 中,我们将其称为 String 数据,例外是在 Java 中无 String 长度限制)。
将一些值插入表格
清单 23 调用 executeUpdate 方法将一个值插入表格第一行每一列中。
stmt.executeUpdate(
"INSERT INTO myTable(test_id, " +
"test_val) VALUES(1,'One')");
清单 23
|
整数值 1 插入名称为 test_id的列中, 三个字符, One,插入名称为 test_val 的列中。
将值插入四个以上行中
清单 24 连续调用 executeUpdate 方法四次,将值插入第 2 至 5 行的列中。 您应能够检查 SQL 命令和确定插入表格中的值。
stmt.executeUpdate(
"INSERT INTO myTable(test_id, " +
"test_val) VALUES(2,'Two')");
stmt.executeUpdate(
"INSERT INTO myTable(test_id, " +
"test_val) VALUES(3,'Three')");
stmt.executeUpdate(
"INSERT INTO myTable(test_id, " +
"test_val) VALUES(4,'Four')");
stmt.executeUpdate(
"INSERT INTO myTable(test_id, " +
"test_val) VALUES(5,'Five')");
清单 24
|
填充表格
此时,已用数据填充名称为 myTable 的表格中的前五行。 程序中的剩余代码将:
- 访问和显示表格中的所有数据。
- 显示表格特定行中的数据。
- 从数据库删除表格。
获取另一语句对象
清单 25 中的代码获取 Statement 对象,如图所示由传递给 createStatement 方法的参数进行初始化。
stmt = con.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
清单 25
|
我不会试图解释初始化参数的含义。 而是,我将让您查看针对 ResultSet 接口的 Sun 文档,然后可能进行一步研究 SQL 书籍。
ResultSet接口提供十个可用作此方法参数的符号常量。该参数的值控制由随后的查询根据Statement对象所返回的 ResultSet 对象的属性。
查询数据库
对此点的所有数据库操作都是基于使用 Statement 接口的 executeUpdate 方法。 重新调用我此前告诉您的 executeUpdate 方法可以用于执行不返回任何结果的 SQL 命令。
现在,我们已达到要执行返回某些结果的 SQL 命令的点。 为此,我们将对 Statement 对象调用 executeQuery 方法。
Sun 的看法是什么?
下面是 Sun 对此方法的部分看法:
"公共 ResultSet executeQuery(String sql) 抛出 SQLException
执行指定的 SQL 语句,返回单独的 ResultSet 对象。
参数:sql - 要发送给数据库的 SQL 语句,通常是静态 SQL SELECT 语句
返回:包含指定查询生成的数据的 ResultSet 对象;从不为空"
换句话说,此方法将在数据库中执行 SQL 命令,并将返回的值封装在 ResultSet 类型的对象中。
ResultSet 对象
ResultSet对象访问封装的数据表。 对象保持光标指向数据的当前行。 最初,光标定位在第一行前面。 下一种方法是将光标移至下一行(与 Java 中的迭代器或计数器类似)。
结果封装在 ResultSet 对象之后,ResultSet 接口提供多种可用于析取对象信息的方法。
ResultSet 对象的方法
get 方法(例如 getString)检索当前行的列值。您可以使用列的索引号或列的名称来检索值。我明白使用列值更有效,但我无法提供您有关这方面的参考。
(列的编号以 1 开始,而非以 0 开始。)
对于 get 方法,JDBC 驱动程序尝试将基本数据转换为指定的 Java 类型并返回合适的 Java 值。
ResultSet 对象的寿命
ResultSet 对象可由 Statement 对象自动关闭,该对象是在 Statement 对象被关闭、重新执行或用于从一系列多个结果中检索下一结果时生成。
执行查询
清单 26 调用 executeQuery 方法执行对数据库的查询,选择所有行的中所有列,并且在名称为 test_id 的列中按值的顺序对结果进行排序。 结果封装在被名称为 rs的参考变量所引用的 ResultSet 对象中。
rs = stmt.executeQuery("SELECT * " +
"from myTable ORDER BY test_id");
清单 26
|
显示 ResultSet 对象中的所有结果
清单 27 使用 while 循环:
- 一次迭代一行的 ResultSet 对象。
- 调用 getInt 方法获取并将值保存在每一行名称为 test_id 的列中。
- 调用 getString 方法获取并将值保存在每一行名称为 test_val 的列中。
- 在屏幕上显示新输出行的两个值。
System.out.println("Display all results:");
while(rs.next()){
int theInt= rs.getInt("test_id");
String str = rs.getString("test_val");
System.out.println("\ttest_id= " + theInt
+ "\tstr = " + str);
}//end while loop
清单 27
|
输出
清单 27 中的代码生成的输出显示于图 7 中。
Display all results:
test_id= 1 str = One
test_id= 2 str = Two
test_id= 3 str = Three
test_id= 4 str = Four
test_id= 5 str = Five
图 7
|
显示编号 2 行中的数据
清单 28 中的代码对同一 ResultSet对象调用 absolute 方法,以便获取、保存和显示编号 2 行中两列的数据。
System.out.println(
"Display row number 2:");
if( rs.absolute(2) ){
int theInt= rs.getInt("test_id");
String str = rs.getString("test_val");
System.out.println("\ttest_id= " + theInt
+ "\tstr = " + str);
}//end if
清单 28
|
(请注意,在大多数 Java 环境中,行的编号是以 1 开头,而非以 0 开头。尽管不在此处加以演示,但对于列的编号来说同样是真实的。很明显,这是数据库工作中的标准。)
输出
图 8 显示的是由清单 28 中的代码所生成的输出。
Display row number 2:
test_id= 2 str = Two
图 8
|
删除表格、关闭连接和终止
清单 29 调用 executeUpdate 方法从名称为 JunkDB 的数据库中删除名称为 myTable 的表格。
stmt.executeUpdate("DROP TABLE myTable");
con.close();
}catch( Exception e ) {
e.printStackTrace();
}//end catch
}//end main
}//end class Jdbc10
清单 29
|
然后清单 29 关闭连接(注销数据库)和终止程序。
运行程序
我鼓励您按本课程中的描述下载和安装 MySQL 数据库服务器以及 MySQL 连接器。
然后,从本课程将近结束的清单中复制代码。 执行批处理文件。 编译并执行程序。 试验文件和程序、进行更改,并且观察您更改的结果。
我向您介绍了如何下载、安装和准备 MySQL 数据库作为 Windows 平台上的 localhost 服务器与 JDBC 一起使用。
然后,我向您介绍了如何编写三个简单的 JDBC 程序管理数据库服务器和操作存储在 MySQL 数据库中的数据。
完整程序清单
下面显示的是本课程中所讨论的一系列程序、批处理文件和文本文件。
C:\mysql\bin\mysqld-opt --console
pause
|
清单 30 MySqlStart.bat 的内容
C:\mysql\bin\mysqladmin -u root shutdown
pause
|
清单 31 MySqlStop.bat 的内容
c:\mysql\bin\mysql --user=root mysql < MySqlCreateDatabase01.txt
pause
|
清单 32 MySqlCreateDatabase01.bat
CREATE DATABASE JunkDB;
\q
|
清单 33 MySqlCreateDatabase01.txt
c:\mysql\bin\mysql --user=root mysql < MySqlMakeUser01.txt
pause
|
清单 34 MySqlMakeUser01.bat
GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
ON JunkDB.*
TO 'auser'@'localhost'
IDENTIFIED BY 'drowssap';
\q
|
清单 35 MySqlMakeUser01.txt
c:\mysql\bin\mysql --user=root mysql < MySqlRemoveUser01.txt
pause
|
清单 36 MySqlRemoveUser01.bat
REVOKE ALL PRIVILEGES ON *.* FROM 'auser'@'localhost';
REVOKE GRANT OPTION ON *.* FROM 'auser'@'localhost';
DELETE FROM mysql.user WHERE User='auser' and Host='localhost';
FLUSH PRIVILEGES;
\q
|
清单 37 MySqlRemoveUser01.txt
c:\mysql\bin\mysql --user=root mysql < MySqlDropDatabase01.txt
pause
|
清单 38 MySqlDropDatabase01.bat
清单 39 MySqlDropDatabase01.txt
/*File Jdbc11.java
Copyright 2004, R.G.Baldwin
Rev 09/18/04
The purpose of this program is to log onto
the master database named mysql as the default
administrator named root whose password is blank
in order to perform the following updates:
1. Create a new database named JunkDB.
2. Create a new user named auser with a password
of drowssap with broad access to the
database named JunkDB.
These two operations produce no visible output
when successful. However, they produce error
messages in the output when unsuccessful.
This program is the reverse of the program named
Jdbc12, which deletes the database JunkDB and
removes the user named auser.
The MySQL server must be running on localhost
before this program is started.
It is necessary to manually start the MySQL
database server running on localhost. See the
documentation sections 2.2.1.5,Starting the
Server for the First Time and 2.2.1.4 Selecting a
Windows Server. This is accomplished by executing
the following command at the command prompt:
C:\mysql\bin\mysqld-opt --console
Similarly, it is necessary to manually stop the
MySQL database server. See the documentation
Section 2.2.1.6 Starting MySQL from the Windows
Command Line. This is accomplished by executing
the following command at the command prompt:
C:\mysql\bin\mysqladmin -u root shutdown
To install the JDBC interface classes, I copied
the jar file named
mysql-connector-java-3.0.15-ga-bin.jar into the
jre\lib\ext folder of my Java installation. I
did this to avoid having to make changes to the
classpath.
I am currently running SDK v1.4.2. When I
upgrade to a newer version of the SDK, it will be
necessary for me to copy the JDBC jar file into
the jre\lib\ext folder for the new version of the
SDK.
This program produces the following output as
a result of a successful run:
Copyright 2004, R.G.Baldwin
URL: jdbc:mysql://localhost:3306/mysql
Connection: com.mysql.jdbc.Connection@1430b5c
Tested using SDK 1.4.2 under WinXP, MySQL
version 4.0.21-win, and JDBC connector
version mysql-connector-java-3.0.15-ga.
************************************************/
import java.sql.*;
public class Jdbc11 {
public static void main(String args[]){
System.out.println(
"Copyright 2004, R.G.Baldwin");
try {
Statement stmt;
//Register the JDBC driver for MySQL.
Class.forName("com.mysql.jdbc.Driver");
//Define URL of database server for
// database named mysql on the localhost
// with the default port number 3306.
String url =
"jdbc:mysql://localhost:3306/mysql";
//Get a connection to the database for a
// user named root with a blank password.
// This user is the default administrator
// having full privileges to do anything.
Connection con =
DriverManager.getConnection(
url,"root", "");
//Display URL and connection information
System.out.println("URL: " + url);
System.out.println("Connection: " + con);
//Get a Statement object
stmt = con.createStatement();
//Create the new database
stmt.executeUpdate(
"CREATE DATABASE JunkDB");
//Register a new user named auser on the
// database named JunkDB with a password
// drowssap enabling several different
// privileges.
stmt.executeUpdate(
"GRANT SELECT,INSERT,UPDATE,DELETE," +
"CREATE,DROP " +
"ON JunkDB.* TO 'auser'@'localhost' " +
"IDENTIFIED BY 'drowssap';");
con.close();
}catch( Exception e ) {
e.printStackTrace();
}//end catch
}//end main
}//end class Jdbc11
|
清单 40 Jdbc11.java
/*File Jdbc12.java
Copyright 2004, R.G.Baldwin
Rev 09/18/04
The purpose of this program is to log onto
the master database named mysql as the default
administrator named root whose password is blank
in order to perform the following updates:
1. Remove a user named auser.
2. Delete a database named JunkDB.
These two operations produce no visible output
when successful. However, they produce error
messages in the output when unsuccessful.
This program is the reverse of the program named
Jdbc11, which creates the database named JunkDB
and registers the user named auser on that
database.
The MySQL server must be running on localhost
before this program is started.
It is necessary to manually start the MySQL
database server running on localhost. See the
documentation sections 2.2.1.5,Starting the
Server for the First Time and 2.2.1.4 Selecting a
Windows Server. This is accomplished by executing
the following command at the command prompt:
C:\mysql\bin\mysqld-opt --console
Similarly, it is necessary to manually stop the
MySQL database server. See the documentation
Section 2.2.1.6 Starting MySQL from the Windows
Command Line. This is accomplished by executing
the following command at the command prompt:
C:\mysql\bin\mysqladmin -u root shutdown
To install the JDBC interface classes, I copied
the jar file named
mysql-connector-java-3.0.15-ga-bin.jar into the
jre\lib\ext folder of my Java installation. I
did this to avoid having to make changes to the
classpath.
I am currently running SDK v1.4.2. When I
upgrade to a newer version of the SDK, it will be
necessary for me to copy the JDBC jar file into
the jre\lib\ext folder for the new version of the
SDK.
This program produces the following output as
a result of a successful run:
Copyright 2004, R.G.Baldwin
URL: jdbc:mysql://localhost:3306/mysql
Connection: com.mysql.jdbc.Connection@1430b5c
Tested using SDK 1.4.2 under WinXP, MySQL
version 4.0.21-win, and JDBC connector
version mysql-connector-java-3.0.15-ga.
************************************************/
import java.sql.*;
public class Jdbc12 {
public static void main(String args[]){
System.out.println(
"Copyright 2004, R.G.Baldwin");
try {
Statement stmt;
//Register the JDBC driver for MySQL.
Class.forName("com.mysql.jdbc.Driver");
//Define URL of database server for
// database named mysql on the localhost
// with the default port number 3306.
String url =
"jdbc:mysql://localhost:3306/mysql";
//Get a connection to the database for a
// user named root with a blank password.
// This user is the default administrator
// having full privileges to do anything.
Connection con =
DriverManager.getConnection(
url,"root", "");
//Display URL and connection information
System.out.println("URL: " + url);
System.out.println("Connection: " + con);
//Get a Statement object
stmt = con.createStatement();
//Remove the user named auser
stmt.executeUpdate(
"REVOKE ALL PRIVILEGES ON *.* " +
"FROM 'auser'@'localhost'");
stmt.executeUpdate(
"REVOKE GRANT OPTION ON *.* " +
"FROM 'auser'@'localhost'");
stmt.executeUpdate(
"DELETE FROM mysql.user WHERE " +
"User='auser' and Host='localhost'");
stmt.executeUpdate("FLUSH PRIVILEGES");
//Delete the database
stmt.executeUpdate(
"DROP DATABASE JunkDB");
con.close();
}catch( Exception e ) {
e.printStackTrace();
}//end catch
}//end main
}//end class Jdbc12
|
清单 41 Jdbc12.java
/*File Jdbc10.java
Copyright 2004, R.G.Baldwin
Rev 09/16/04
The purpose of this program is to test the
ability to use JDBC to access a MySQL database
server on localhost.
The MySQL server must be running on localhost
before this program is started. In addition, a
database named JunkDB must have been created and
a user named auser must have been registered on
that database with a password of drowssap before
this program is started.
It is necessary to manually start the MySQL
database server running on localhost. See the
documentation sections 2.2.1.5,Starting the
Server for the First Time and 2.2.1.4 Selecting a
Windows Server. This is accomplished by executing
the following command at the command prompt:
C:\mysql\bin\mysqld-opt --console
Similarly, it is necessary to manually stop the
MySQL database server. See the documentation
Section 2.2.1.6 Starting MySQL from the Windows
Command Line. This is accomplished by executing
the following command at the command prompt:
C:\mysql\bin\mysqladmin -u root shutdown
You can prepare MySQL for use in three
alternative ways:
1. Using the control program named mysql located
in folder C:\mysql\bin in interactive mode.
2. Using a batch file to start the mysql program
along with a text file to provide the input.
3. By running the Java programs named Jdbc11 and
Jdbc12.
See the MySQL documentation Section 3.5, entitled
Using mysql in Batch Mode, for an explanation of
how to access the MySQL database server using
batch files and text files.
There is one bat file and one txt file used in
each case. The bat file logs into the mysql
monitor program as root having administrator
privileges and points to the txt file, which
provides the commands that are executed by the
monitor program.
The following two files create a new database
named JunkDB. See the documentation Section 3.3,
entitled Creating and Using a Database.
MySqCreateDatabase01.bat
MySqlCreateDatabase01.txt
The following two files make a new user named
auser registered on the database named JunkDB
with a password of drowssap. This user can
access the JunkDB database, but only from
localhost. See the documentation Section 5.6.2,
entitled Adding New User Accounts to MySQL.
MySqlMakeUser01.bat
MySqlMakeUser01.txt
Another way to create the database and register
a user named auser on that database is to run
the Java program named Jdbc11.
The following two files delete the database named
JunkDB. See documentation Section 14.2.8, DROP
DATABASE Syntax.
MySqDropDatabase01.bat
MySqlDropDatabase01.txt
The following two files remove the user named
auser. See the documentation Section 5.6.3,
Removing User Accounts from MySQL.
MySqlRemoveUser01.bat
MySqlRemoveUser01.txt
Another way to delete a database named JunkDB
and remove the user named auser is to run the
program named Jdbc12.
This program:
Accesses the database named JunkDB,
Creates a table named myTable,
Puts five rows of data into the table,
Displays the data,
Deletes the table.
Two different approaches are used to display the
contents of the table. The first approach
displays all of the data in the table. The
second approach displays only the data in a
specific row in the table.
As a precaution, before attempting to create the
new table, the program attempts to delete a table
having the same name. If a table having the same
name already exists as residue from a previous
run, it is deleted. If it doesn't already exist
when the attempt is made to delete it, an
exception is thrown. This exception is simply
caught and ignored.
To install the JDBC interface classes, I copied
the jar file named
mysql-connector-java-3.0.15-ga-bin.jar into the
jre\lib\ext folder of my Java installation. I
did this to avoid having to make changes to the
classpath.
I am currently running SDK v1.4.2. When I
upgrade to a newer version of the SDK, it will be
necessary for me to copy the JDBC jar file into
the jre\lib\ext folder for the new version of the
SDK.
This program produces the following output under
normal conditions where the table named myTable
does not exist when the program is started (the
specifics regarding the Connection object may
vary from one run to the next):
Copyright 2004, R.G.Baldwin
URL: jdbc:mysql://localhost:3306/JunkDB
Connection: com.mysql.jdbc.Connection@1430b5c
java.sql.SQLException: Base table or view not
found message from server: "Unknown table
'mytable'"No existing table to delete
Display all results:
test_id= 1 str = One
test_id= 2 str = Two
test_id= 3 str = Three
test_id= 4 str = Four
test_id= 5 str = Five
Display row number 2:
test_id= 2 str = Two
Tested using SDK 1.4.2 under WinXP, MySQL
version 4.0.21-win, and JDBC connector
version mysql-connector-java-3.0.15-ga.
************************************************/
import java.sql.*;
public class Jdbc10 {
public static void main(String args[]){
System.out.println(
"Copyright 2004, R.G.Baldwin");
try {
Statement stmt;
ResultSet rs;
//Register the JDBC driver for MySQL.
Class.forName("com.mysql.jdbc.Driver");
//Define URL of database server for
// database named JunkDB on the localhost
// with the default port number 3306.
String url =
"jdbc:mysql://localhost:3306/JunkDB";
//Get a connection to the database for a
// user named auser with the password
// drowssap, which is password spelled
// backwards.
Connection con =
DriverManager.getConnection(
url,"auser", "drowssap");
//Display URL and connection information
System.out.println("URL: " + url);
System.out.println("Connection: " + con);
//Get a Statement object
stmt = con.createStatement();
//As a precaution, delete myTable if it
// already exists as residue from a
// previous run. Otherwise, if the table
// already exists and an attempt is made
// to create it, an exception will be
// thrown.
try{
stmt.executeUpdate("DROP TABLE myTable");
}catch(Exception e){
System.out.print(e);
System.out.println(
"No existing table to delete");
}//end catch
//Create a table in the database named
// myTable.
stmt.executeUpdate(
"CREATE TABLE myTable(test_id int," +
"test_val char(15) not null)");
//Insert some values into the table
stmt.executeUpdate(
"INSERT INTO myTable(test_id, " +
"test_val) VALUES(1,'One')");
stmt.executeUpdate(
"INSERT INTO myTable(test_id, " +
"test_val) VALUES(2,'Two')");
stmt.executeUpdate(
"INSERT INTO myTable(test_id, " +
"test_val) VALUES(3,'Three')");
stmt.executeUpdate(
"INSERT INTO myTable(test_id, " +
"test_val) VALUES(4,'Four')");
stmt.executeUpdate(
"INSERT INTO myTable(test_id, " +
"test_val) VALUES(5,'Five')");
//Get another statement object initialized
// as shown.
stmt = con.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
//Query the database, storing the result
// in an object of type ResultSet
rs = stmt.executeQuery("SELECT * " +
"from myTable ORDER BY test_id");
//Use the methods of class ResultSet in a
// loop to display all of the data in the
// database.
System.out.println("Display all results:");
while(rs.next()){
int theInt= rs.getInt("test_id");
String str = rs.getString("test_val");
System.out.println("\ttest_id= " + theInt
+ "\tstr = " + str);
}//end while loop
//Display the data in a specific row using
// the rs.absolute method.
System.out.println(
"Display row number 2:");
if( rs.absolute(2) ){
int theInt= rs.getInt("test_id");
String str = rs.getString("test_val");
System.out.println("\ttest_id= " + theInt
+ "\tstr = " + str);
}//end if
//Delete the table and close the connection
// to the database
stmt.executeUpdate("DROP TABLE myTable");
con.close();
}catch( Exception e ) {
e.printStackTrace();
}//end catch
}//end main
}//end class Jdbc10
|
清单 42 Jdbc10.java
Copyright 2004, Richard G. Baldwin. 未征得 Richard Baldwin 的明确书面许可,禁止以任何形式或介质完整或部分复制本文档。
关于作者
Richard Baldwin 是德克萨斯州奥斯汀社区大学的一位大学教授,并且是一位主要致力于 Java、C# 和 XML 的私人顾问。他认为 Java 和 C# 应用程序除了有许多独立于平台和/或语言的优点之外,Java、C# 和 XML 将成为提供 Web 结构信息的主要推动力量。
Richard 参与了大量咨询项目,他经常为位于德克萨斯州奥斯汀或周围附近的高科技公司提供现场培训。 他是 Baldwin 编程指南的作者,获得了世界各地经验丰富和有抱负追求的编程人员的广泛赞誉。他还在 JavaPro 杂志上发表了许多文章。
Richard 拥有 Southern Methodist 大学的 MSEE 学位,在计算技术应用于解决现实世界的问题方面拥有多年的经验。
Baldwin@DickBaldwin.com
|