Java编程思想第4版[中文版](PDF格式)-第149部分
按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
感,所以可以选用的第一种子协议就是“jdbc…odbc 桥”,它用“odbc”关键字即可指定。
(3) 数据库标识符:随使用的数据库驱动程序的不同而变化,但一般都提供了一个比较符合逻辑的名称,由
数据库管理软件映射(对应)到保存了数据表的一个物理目录。为使自己的数据库标识符具有任何含义,必
须用自己的数据库管理软件为自己喜欢的名字注册(注册的具体过程又随运行平台的不同而变化)。
所有这些信息都统一编译到一个字串里,即“数据库URL”。举个例子来说,若想通过ODBC 子协议同一个标
576
…………………………………………………………Page 578……………………………………………………………
识为“people”的数据库连接,相应的数据库URL 可设为:
String dbUrl = 〃jdbc:odbc:people〃
如果通过一个网络连接,数据库URL 也需要包含对远程机器进行标识的信息。
准备好同数据库连接后,可调用静态方法 DriverManager。getConnection(),将数据库的URL 以及进入那个
数据库所需的用户名密码传递给它。得到的返回结果是一个Connection 对象,利用它即可查询和操纵数据
库。
下面这个例子将打开一个联络信息数据库,并根据命令行提供的参数查询一个人的姓(Last Name)。它只选
择那些有 E…mail 地址的人的名字,然后列印出符合查询条件的所有人:
//: Lookup。java
// Looks up email addresses in a
// local database using JDBC
import java。sql。*;
public class Lookup {
public static void main(String'' args) {
String dbUrl = 〃jdbc:odbc:people〃;
String user = 〃〃;
String password = 〃〃;
try {
// Load the driver (registers itself)
Class。forName(
〃sun。jdbc。odbc。JdbcOdbcDriver〃);
Connection c = DriverManager。getConnection(
dbUrl; user; password);
Statement s = c。createStatement();
// SQL code:
ResultSet r =
s。executeQuery(
〃SELECT FIRST; LAST; EMAIL 〃 +
〃FROM people。csv people 〃 +
〃WHERE 〃 +
〃(LAST='〃 + args'0' + 〃') 〃 +
〃 AND (EMAIL Is Not Null) 〃 +
〃ORDER BY FIRST〃);
while(r。next()) {
// Capitalization doesn't matter:
System。out。println(
r。getString(〃Last〃) + 〃; 〃
+ r。getString(〃fIRST〃)
+ 〃: 〃 + r。getString(〃EMAIL〃) );
}
s。close(); // Also closes ResultSet
} catch(Exception e) {
e。printStackTrace();
}
}
} ///:~
可以看到,数据库URL 的创建过程与我们前面讲述的完全一样。在该例中,数据库未设密码保护,所以用户
名和密码都是空串。
用DriverManager。getConnection()建好连接后,接下来可根据结果Connection 对象创建一个Statement
577
…………………………………………………………Page 579……………………………………………………………
(语句)对象,这是用createStatement()方法实现的。根据结果 Statement,我们可调用
executeQuery(),向其传递包含了SQL…92 标准SQL 语句的一个字串(不久就会看到如何自动创建这类语句,
所以没必要在这里知道关于SQL 更多的东西)。
executeQuery()方法会返回一个ResultSet (结果集)对象,它与继承器非常相似:next()方法将继承器移
至语句中的下一条记录;如果已抵达结果集的末尾,则返回null 。我们肯定能从executeQuery()返回一个
ResultSet 对象,即使查询结果是个空集(也就是说,不会产生一个违例)。注意在试图读取任何记录数据
之前,都必须调用一次 next()。若结果集为空,那么对next()的这个首次调用就会返回false。对于结果集
中的每条记录,都可将字段名作为字串使用(当然还有其他方法),从而选择不同的字段。另外要注意的是
字段名的大小写是无关紧要的——SQL 数据库不在乎这个问题。为决定返回的类型,可调用getString(),
getFloat()等等。到这个时候,我们已经用Java 的原始格式得到了自己的数据库数据,接下去可用 Java 代
码做自己想做的任何事情了。
15。7。1 让示例运行起来
就JDBC 来说,代码本身是很容易理解的。最令人迷惑的部分是如何使它在自己特定的系统上运行起来。之所
以会感到迷惑,是由于它要求我们掌握如何才能使JDBC 驱动程序正确装载,以及如何用我们的数据库管理软
件来设置一个数据库。
当然,具体的操作过程在不同的机器上也会有所区别。但这儿提供的在32 位Windows 环境下操作过程可有效
帮助大家理解在其他平台上的操作。
1。 步骤 1:寻找JDBC 驱动程序
上述程序包含了下面这条语句:
Class。forName(〃sun。jdbc。odbc。JdbcOdbcDriver〃);
这似乎暗示着一个目录结构,但大家不要被它蒙骗了。在我手上这个 JDK 1。1 安装版本中,根本不存在叫作
JdbcOdbcDriver。class 的一个文件。所以假如在看了这个例子后去寻找它,那么必然会徒劳而返。另一些人
提供的例子使用的是一个假名字,如“myDriver。ClassName ”,但人们从字面上得不到任何帮助。事实上,
上述用于装载jdbc…odbc 驱动程序(实际是与JDK 1。1 配套提供的唯一驱动)的语句在联机文档的多处地方
均有出现(特别是在一个标记为“JDBC…ODBC Bridge Driver ”的页内)。若上面的装载语句不能工作,那么
它的名字可能已随着Java 新版本的发布而改变了;此时应到联机文档里寻找新的表述方式。
若装载语句出错,会在这个时候得到一个违例。为了检验驱动程序装载语句是不是能正常工作,请将该语句
后面直到catch 从句之间的代码暂时设为注释。如果程序运行时未出现违例,表明驱动程序的装载是正确
的。
2。 步骤2:配置数据库
同样地,我们只限于在 32 位 Windows 环境中工作;您可能需要研究一下自己的操作系统,找出适合自己平台
的配置方法。
首先打开控制面板。其中可能有两个图标都含有“ODBC ”字样,必须选择那个“32 位ODBC ”,因为另一个是
为了保持与 16位软件的向后兼容而设置的,和JDBC 混用没有任何结果。双击“32 位ODBC ”图标后,看到的
应该是一个卡片式对话框,上面一排有多个卡片标签,其中包括“用户DSN”、“系统DSN”、“文件DSN”
等等。其中,“DSN”代表“数据源名称”(Data Source Name)。它们都与JDBC…ODBC 桥有关,但设置数据
库时唯一重要的地方“系统DSN”。尽管如此,由于需要测试自己的配置以及创建查询,所以也需要在“文
件DSN”中设置自己的数据库。这样便可让Microsoft Query 工具(与Microsoft Office 配套提供)正确地
找到数据库。注意一些软件公司也设计了自己的查询工具。
最有趣的数据库是我们已经使用过的一个。标准ODBC 支持多种文件格式,其中包括由不同公司专用的一些格
式,如 dBASE。然而,它也包括了简单的“逗号分隔ASCII”格式,它几乎是每种数据工具都能够生成的。就
目前的例子来说,我只选择自己的“people”数据库。这是我多年来一直在维护的一个数据库,中间使用了
各种联络管理工具。我把它导出成为一个逗号分隔的ASCII 文件(一般有个。csv 扩展名,用 Outlook
Express 导出通信簿时亦可选用同样的文件格式)。在“文件DSN”区域,我按下“添加”按钮,选择用于控
制逗号分隔 ASCII 文件的文本驱动程序(Micr osoft Text Driver),然后撤消对“使用当前目录”的选择,
以便导出数据文件时可以自行指定目录。
大家会注意到在进行这些工作的时候,并没有实际指定一个文件,只是一个目录。那是因为数据库通常是由
某个目录下的一系列文件构成的(尽管也可能采用其他形式)。每个文件一般都包含了单个“数据表”,而
且SQL 语句可以产生从数据库中多个表摘取出来的结果(这叫作“联合”,或者 join )只包含了单张表的数
578
…………………………………………………………Page 580……………………………………………………………
据库(就象目前这个)通常叫作“平面文件数据库”。对于大多数问题,如果已经超过了简单的数据存储与
获取力所能及的范围,那么必须使用多个数据表。通过“联合”,从而获得希望的结果。我们把这些叫作
“关系型”数据库。
3。 步骤3:测试配置
为了对配置进行测试,需用一种方式核实数据库是否可由查询它的一个程序“见到”。当然,可以简单地运
行上述的JDBC 示范程序,并加入下述语句:
Connection c = DriverManager。getConnection(
dbUrl; user; password);
若掷出一个违例,表明你的配置有误。
然而,此时很有必要使用一个自动化的查询生成工具。我使用的是与Microsoft Office 配套提供的
Microsoft Query,但你完全可以自行选择一个。查询工具必须知道数据库在什么地方,而Microsoft Query
要求我进入 ODBC Administrator 的“文件DSN”卡片,并在那里新添一个条目。同样指定文本驱动程序以及
保存数据库的目录。虽然可将这个条目命名为自己喜欢的任何东西,但最好还是使用与“系统DSN”中相同
的名字。
做完这些工作后,再用查询工具创建一个新查询时,便会发现自己的数据库可以使用了。
4。 步骤4:建立自己的SQL 查询
我用Microsoft Query 创建的查询不仅指出目标数据库存在且次序良好,也会自动生成 SQL 代码,以便将其
插入我自己的Java 程序。我希望这个查询能够检查记录中是否存在与启动Java 程序时在命令行键入的相同
的“姓”(Last Name)。所以作为一个起点,我搜索自己的姓“Eckel”。另外,我希望只显示出有对应E
mail 地址的那些名字。创建这个查询的步骤如下:
(1) 启动一个新查询,并使用查询向导(Query Wizard)。选择“people”数据库(等价于用适应的数据库
URL 打开数据库连接)。
(2) 选择数据库中的“people”表。从这张数据表中,选择FIRST,LAST 和 EMAIL 列。
(3) 在“Filter Data”(过滤器数据库)下,选择LAST,并选择“equals”(等于),加上参数Eckel。点
选“And”单选钮。
(4) 选择EMAIL,并选中“Is not Null”(不为空)。
(5) 在“Sort By”下,选择FIRST。
查询结果会向我们展示出是否能得到自己希望的东西。
现在可以按下SQL 按钮。不需要我们任何方面的介入,正确的 SQL 代码会立即弹现出来,以便我们粘贴和复
制。对于这个查询,相应的SQL 代码如下:
SELECT people。FIRST; people。LAST; people。EMAIL
FROM people。csv people
WHERE (people。LAST='Eckel') AND
(people。EMAIL Is Not Null)
ORDER BY people。FIRST
若查询比较复杂,手工编码极易出错。但利用一个查询工具,就可以交互式地测试自己的查询,并自动获得
正确的代码。事实上,亲手为这些事情编码是难以让人接受的。
5。 步骤5:在自己的查询中修改和粘贴
我们注意到上述代码与程序中使用的代码是有所区别的。那是由于查询工具对所有名字都进行了限定,即便
涉及的仅有一个数据表(若真的涉及多个数据表,这种限定可避免来自不同表的同名数据列发生冲突)。由
于这个查询只需要用到一个数据表,所以可考虑从大多数名字中删除“people”限定符,就象下面这样:
SELECT FIRST; LAST; EMAIL
FROM people。csv people
WHERE (LAST='Eckel') AND
(EMAIL Is Not Null)
579
…………………………………………………………Page 581……………………………………………………………
ORDER BY FIRST
此外,我们不希望“硬编码”这个程序,从而只能查找一个特定的名字。相反,它应该能查找我们在命令行
动态提供的一个名字。所以还要进行必要的修改,并将SQL 语句转换成一个动态生成的字串。如下所示:
〃SELECT FIRST; LAST; EMAIL 〃 +
〃FROM people。csv people 〃 +
〃WHERE 〃 +
〃(LAST='〃 + args'0' + 〃') 〃 +
〃 AND (E