Java数据库连接

Java数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。JDBC也是Sun Microsystems的商标。我们通常说的JDBC是面向关系型数据库的。

JDBC驱动程序共分四种类型:

JDBC-ODBC桥

这种类型的驱动把所有JDBC的调用传递给ODBC,再让后者调用数据库本地驱动代码(也就是数据库厂商提供的数据库操作二进制代码库,例如Oracle中的oci.dll)。

本地API驱动

这种类型的驱动通过客户端加载数据库厂商提供的本地代码库(C/C++等)来访问数据库,而在驱动程序中则包含了Java代码。

网络协议驱动

这种类型的驱动给客户端提供了一个网络API,客户端上的JDBC驱动程序使用套接字(Socket)来调用服务器上的中间件程序,后者在将其请求转化为所需的具体API调用。

本地协议驱动

这种类型的驱动使用Socket,直接在客户端和数据库间通信。

JDBC API主要位于JDK中的java.sql包中(之后扩展的内容位于javax.sql包中),主要包括(斜体代表接口,需驱动程序提供者来具体实现):

DriverManager:负责加载各种不同驱动程序(Driver),并根据不同的请求,向调用者返回相应的数据库连接(Connection)。Driver:驱动程序,会将自身加载到DriverManager中去,并处理相应的请求并返回相应的数据库连接(Connection)。Connection:数据库连接,负责与进行数据库间通讯,SQL执行以及事务处理都是在某个特定Connection环境中进行的。可以产生用以执行SQL的Statement。Statement:用以执行SQL查询和更新(针对静态SQL语句和单次执行)。PreparedStatement:用以执行包含动态参数的SQL查询和更新(在服务器端编译,允许重复执行以提高效率)。CallableStatement:用以调用数据库中的存储过程。SQLException:代表在数据库连接的建立和关闭和SQL语句的执行过程中发生了例外情况(即错误)。

数据类型的映射

SQL类型

Java类型

CHAR

java.lang.String

VARCHAR

java.lang.String

LONGVARCHAR

java.lang.String

NUMERIC

java.math.BigDecimal

DECIMAL

java.math.BigDecimal

BIT

boolean

TINYINT

byte

SMALLINT

short

INTEGER

int

BIGINT

long

REAL

float

FLOAT

double

DOUBLE

double

BINARY

byte[]

VARBINARY

byte[]

LONGVARBINARY

byte[]

DATE

java.sql.Date

TIME

java.sql.Time

TIMESTAMP

java.sql.Timestamp

BLOB

java.sql.Blob

CLOB

java.sql.Clob

Array

java.sql.Array

REF

java.sql.Ref

Struct

java.sql.Struct

注:这种类型匹配不是强制性标准,特定的JDBC厂商可能会改变这种类型匹配。例如Oracle中的DATE类型是包含时分秒,而java.sql.Date仅仅支持年月日。

下面罗列了各种数据库使用JDBC连接的方式:

⒈Oracle8/8i/9i数据库(thin模式)

⒉DB2数据库

⒊Sql Server7.0/2000数据库

⒋Sybase数据库

⒌Informix数据库

⒍MySQL数据库

⒎PostgreSQL数据库

⒏access数据库直连用ODBC的

当访问一个远程数据库时,JDBC将利用Internet文件的编址方案和一个看起来很像网页地址(统一资源定位器URL)的文件名。

JDBC为程序员指定了一组在编写SQL请求时使用的面向对象的类。还有一组附加的类描述了JDBC驱动API。能映射成Java数据类型的最普通的SQL数据类型都是支持的。这个API提供了微软事务服务器请求的执行支持以及提交和回滚到事务开始的能力。

与数据库建立连接

发送 SQL 语句

处理结果

JDBC 是个"低级"接口,也就是说,它用于直接调用 SQL 命令。在这方面它的功能极佳,并比其它的数据库连接 API 易于使用,但它同时也被设计为一种基础接口,在它之上可以建立高级接口和工具。高级接口是"对用户友好的"接口,它使用的是一种更易理解和更为方便的 API,这种API在幕后被转换为诸如 JDBC 这样的低级接口。

在关系数据库的"对象/关系"映射中,表中的每行对应于类的一个实例,而每列的值对应于该实例的一个属性。于是,程序员可直接对 Java 对象进行操作;存取数据所需的 SQL 调用将在"掩盖下"自动生成。此外还可提供更复杂的映射,例如将多个表中的行结合进一个 Java 类中。

随着人们对 JDBC 的兴趣日益增涨,越来越多的开发人员一直在使用基于 JDBC 的工具,以使程序的编写更加容易。程序员也一直在编写力图使最终用户对数据库的访问变得更为简单的应用程序。例如应用程序可提供一个选择数据库任务的菜单。任务被选定后,应用程序将给出提示及空白供填写执行选定任务所需的信息。所需信息输入应用程序将自动调用所需的 SQL 命令。在这样一种程序的协助下,即使用户根本不懂 SQL 的语法,也可以执行数据库任务。

JDBC API 既支持数据库访问的两层模型(C/S),同时也支持三层模型(B/S)。在两层模型中,Java applet或应用程序将直接与数据库进行对话。这将需要一个JDBC驱动程序来与所访问的特定数据库管理系统进行 通讯。用户的SQL语句被送往数据库中,而其结果将被送回给用户。数据库可以位于另一台计算机上,用户通过网络连接到上面。这就叫做客户机/服务器配置,其中用户的计算机为客户机,提供数据库的计算机为服务器。网络可以是 Intranet(它可将公司职员连接起来),也可以是 Internet。

在三层模型中,命令先是被发送到服务的"中间层",然后由它将SQL 语句发送给数据库。数据库对 SQL 语句进行处理并将结果送回到中间层,中间层再将结果送回给用户。MIS 主管们都发现三层模型很吸引人,因为可用中间层来控制对公司数据的访问和可作的的更新的种类。中间层的另一个好处是,用户可以利用易于使用的高级API,而中间层将把它转换为相应的低级调用。最后,许多情况下三层结构可提供一些性能上的好处。

到目前为止,中间层通常都用 C 或 C++ 这类语言来编写,这些语言执行速度较快。然而,随着最优化编译器(它把 Java 字节代码转换为高效的特定于机器的代码)的引入,用 Java 来实现中间层将变得越来越实际。这将是一个很大的进步,它使人们可以充分利用 Java 的诸多优点(如坚固、多线程和安全等特征)。JDBC 对于从Java的中间层来访问数据库非常重要。

结构化查询语言 (SQL) 是访问关系数据库的标准语言。困难之处在于:虽然大多数的 DBMS(数据库管理系统)对其基本功能都使用了标准形式的 SQL,但它们却不符合为更高级的功能定义的标准 SQL 语法或语义。例如,并非所有的数据库都支持储存程序或外部连接,那些支持这一功能的数据库又相互不一致。人们希望 SQL 中真正标准的那部份能够进行扩展以包括越来越多的功能。但同时 JDBC API 又必须支持现有的 SQL。

JDBC API 解决这个问题的一种方法是允许将任何查询字符串一直传到所涉及的 DBMS 驱动程序上。这意味着应用程序可以使用任意多的 SQL 功能,但它必须冒这样的风险:有可能在某些 DBMS 上出错。事实上,应用程序查询甚至不一定要是 SQL,或者说它可以是个为特定的 DBMS 设计的 SQL 的专用派生物(例如,文档或图象查询)。

JDBC 处理 SQL 一致性问题的第二种方法是提供 ODBC 风格的转义子句,这将在后续部分中讨论。转义语法为几个常见的 SQL 分歧提供了一种标准的 JDBC 语法。例如,对日期文字和已储存过程的调用都有转义语法。

对于复杂的应用程序,JDBC 用第三种方法来处理 SQL 的一致性问题它利用 DatabaseMetaData 接口来提供关于 DBMS 的描述性信息,从而使应用程序能适应每个 DBMS 的要求和功能。

由于 JDBC API 将用作开发高级数据库访问工具和 API 的基础 API,因此它还必须注意其所有上层建筑的一致性。"符合JDBC标准TM" 代表用户可依赖的 JDBC 功能的标准级别。要使用这一说明,驱动程序至少必须支持 ANSI SQL-2 Entry Level(ANSI SQL-2 代表美国国家标准局 1992 年所采用的标准。Entry Level代表SQL功能的特定清单)。驱动程序开发人员可用 JDBC API 所带的测试工具包来确定他们的驱动程序是否符合这些标准。

"符合 JDBC 标准TM" 表示提供者的 JDBC 实现已经通过了JavaSoft 提供的一致性测试。这些一致性测试将检查 JDBC API中定义的所有类和方法是否都存在,并尽可能地检查程序是否具有SQL Entry Level 功能。当然,这些测试并不完全,而且 JavaSoft 也无意对各提供者的实现进行标级。但这种一致性定义的确可对JDBC实现提供一定的可信度。随着越来越多的数据库提供者、连接提供者、Internet 提供者和应用程序编程员对 JDBC API 的接受,JDBC 也正迅速成为 Java 数据库访问的标准。

建议链接的五大步骤:

1加载(注册)数据库

2 建立链接

3 执行SQL语句

4 处理结果集

5 关闭数据库

教程:JDBC 入门 作者:Maydene Fisher 翻译:comer

你需要做的第一事情是你与想要使用的 DBMS 建立一个连接。这包含 2 个步骤:装载驱动程序并建立连接。

装载驱动程序

装载驱动程序只需要非常简单的一行代码。例如,你想要使用 JDBC-ODBC 桥驱动程序,可以用下列代码装载它:

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

你的驱动程序文档将告诉你应该使用的类名。例如, 如果类名是 jdbc.DriverXYZ ,你将用代码以下的代码装载驱动程序:

Class.forName("jdbc.DriverXYZ");

你不需要创建一个驱动程序类的实例并且用 DriverManager 登记它,因为调用 Class.forName 将自动将加载驱动程序类。如果你曾自己创建实例,你将创建一个不必要的副本,但它不会带来什么坏处。

加载 Driver 类后,它们即可用来与数据库建立连接。

建立连接

第二步就是用适当的驱动程序类与 DBMS 建立一个连接。下列代码是一般的做法:

Connection con = DriverManager.getConnection(url,"myLogin","myPassword");

这个步骤也非常简单,最难的是怎么提供 url。如果你正在使用 JDBC-ODBC 桥, JDBC URL 将以 jdbc:odbc 开始:余下 URL 通常是你的数据源名字或数据库系统。因此,假设你正在使用 ODBC 存取一个叫 "Fred" 的 ODBC 数据源,你的 JDBC URL 是 jdbc:odbc:Fred。把 "myLogin" 及 "myPassword" 替换为你登陆 DBMS 的用户名及口令。如果你登陆数据库系统的用户名为 "Fernanda" 口令为 "J8",只需下面的 2 行代码就可以建立一个连接:

String url = "jdbc:odbc:Fred";

Connection con = DriverManager.getConnection(url,"Fernanda","J8");

如果你使用的是第三方开发了的 JDBC驱动程序,文档将告诉你该使用什么 subprotocol, 就是在 JDBC URL 中放在 jdbc 后面的部分。例如,如果驱动程序开发者注册了 acme 作为 subprotocol, JDBC URL 的第一和第二部分将是 jdbc:acme。驱动程序文档也会告诉你余下 JDBC URL 的格式。JDBC URL 最后一部分提供了定位数据库的信息。

如果你装载的驱动程序识别了提供给 DriverManager.getConnection 的 JDBC URL ,那个驱动程序将根据 JDBC URL 建立一个到指定 DBMS 的连接。正如名称所示,DriverManager 类在幕后为你管理建立连接的所有细节。除非你是正在写驱动程序,你可能无需使用此类的其它任何方法,一般程序员需要在此类中直接使用的唯一方法是 DriverManager.getConnection。

DriverManager.getConnection 方法返回一个打开的连接,你可以使用此连接创建 JDBC statements 并发送 SQL 语句到数据库。在前面的例子里,con 对象是一个打开的连接,并且我们要在以后的例子里使用它。

设置表

创建表

首先,我们在我们的示例数据库创建其中一张表 COFFEES,包含在咖啡店所卖咖啡的必要的信息,包括咖啡名字,他们的价格,本星期卖了多少磅及迄今为止卖的数目。

另外,我们应该指出的的是 SQL 语句的格式。在 CREATE TABLE 语句中,关键字采用大写字符,并且每个项目都另起一行。SQL 并没有此要求;仅仅是为了更容易阅读。SQL 标准是不区分关键词的大小写的,

然而,引号里的内容是区分大小写的:在名字"Washington" 里 "W" 必须被大写,并且余下的字符必须是小写的。

对于标识,不同的 DBMS 有不同的要求,例如,某些 DBMSs 要求那些列名及表名必须跟创建时的一样,有些则没有此要求。为安全起见,我们全部使用大写标识如 COFFEES、SUPPLIERS,因为我们是那样定义他们的。

到止我们写了创建 COFFEES 表的 SQL 语句,我们在它外面加上引号(使它成为字符串),并且字符串赋值给变量 createTableCoffees,在以后的 JDBC 代码中我们可以使用此变量。正如看到的,DBMS 并不在意分行,但对 Java 语言来,String 对象分行是通不过编译的。因而,我们可以用加号 (+) 把每一行的串连接。

String createTableCoffees = "CREATE TABLE COFFEES " +

"(COF_NAME VARCHAR(32),SUP_ID INTEGER,PRICE FLOAT," +

"SALES INTEGER,TOTAL INTEGER)";

我们在 CREATE TABLE 语句中使用的数据类型是通用的 SQL 类型(也称 JDBC 类型)它们在类 java.sql.Types 中定义。DBMSs 通常使用这些标准的类型,因此,当你要尝试一些 JDBC 应用程序时,你可以直接使用 CreateCoffees.java 应用程序,它使用了 CREATE TABLE 语句。如果你的 DBMS 使用了它的自己的本地的类型名字,我们为你供应其它的应用程序,我们将在后面详细解释。

在运用任何应用程序前,当然,我们将让你了解 JDBC 的基础。

创建 JDBC Statements 对象

Statement 对象用于把 SQL 语句发送到 DBMS。你只须简单地创建一个 Statement 对象并且然后执行它,使用适当的方法执行你发送的 SQL 语句。对 SELECT 语句来说,可以使用 executeQuery。要创建或修改表的语句,使用的方法是 executeUpdate。

需要一个活跃的连接的来创建 Statement 对象的实例。在下面的例子中,我们使用我们的 Connection 对象 con 创建 Statement 对象 stmt:

Statement stmt = con.createStatement();

到此 stmt 已经存在了,但它还没有把 SQL 语句传递到 DBMS。我们需要提供 SQL 语句作为参数提供给我们使用的 Statement 的方法。例如,在下面的代码段里,我们使用上面例子中的 SQL 语句作为 executeUpdate 的参数:

stmt.executeUpdate("CREATE TABLE COFFEES " +

"(COF_NAME VARCHAR(32),SUP_ID INTEGER,PRICE FLOAT," +

"SALES INTEGER,TOTAL INTEGER)");

因为我们已经把 SQL 语句赋给了 createTableCoffees 变量,我们可以如下方式书写代码:

stmt.executeUpdate(createTableCoffees);

执行语句

我们使用 executeUpdate 方法是因为在 createTableCoffees 中的 SQL 语句是 DDL (数据定义语言)语句。创建表,改变表,删除表都是 DDL 语句的例子,要用 executeUpdate 方法来执行。你也可以从它的名字里看出,方法 executeUpdate 也被用于执行更新表 SQL 语句。实际上,相对于创建表来说,executeUpdate 用于更新表的时间更多,因为表只需要创建一次,但经常被更新。

被使用最多的执行 SQL 语句的方法是 executeQuery。这个方法被用来执行 SELECT 语句,它几乎是使用最多的 SQL 语句。马上你将看到如何使用这个方法。

在表中输入数据

我们已经显示了如何通过指定列名、数据类型来创建表 COFFEES,但是这仅仅建立表的结构。表还没有任何数据。我们将次输入一行数据到表中,提供每列的信息,注意插入的数据显示顺序跟表创建时候是一样的,既缺省顺序。

下列代码插入一个行数据,COF_NAME 的值为 Colombian,SUP_ID 为 101,PRICE 为 7.99,SALES 0,TOTAL 0。就象创建 COFFEES 表一样,我们创建一 Statement 对象,并执行 executeUpdate 方法。

因为 SQL 语句一行显示不下,因此我们把它分为两行,并用加号 (+) 相连。特别要注意的是,在 COFFEES 和 VALUES 之间要有空格。这个空格必须在引号之内并且要在 COFFEES 跟 VALUES 之间;没有这个空格,SQL 语句将被错误地被读作为 "INSERT INTO COFFEESVALUES ...",并且 DBMS 将寻找表 COFFEESVALUES。还要注意的是在 coffee name 上我们使用了单引号。

Statement stmt = con.createStatement();

stmt.executeUpdate(

"INSERT INTO COFFEES " +

"VALUES ('Colombian',101,7.99,0,0)");

下面的代码把第二行插入到表 COFFEES 中。我们可以在使用 Statement 对象而无须为每次执行创建一个新的。

stmt.executeUpdate("INSERT INTO COFFEES " +

"VALUES ('French_Roast',49,8.99,0,0)");

剩下行的数据如下:

stmt.executeUpdate("INSERT INTO COFFEES " +

"VALUES ('Espresso',150,9.99,0,0)");

stmt.executeUpdate("INSERT INTO COFFEES " +

"VALUES ('Colombian_Decaf',101,8.99,0,0)");

stmt.executeUpdate("INSERT INTO COFFEES " +

"VALUES ('French_Roast_Decaf',49,9.99,0,0)");

从表中取得数据

既然表 COFFEES 中已经有数据了,我们就可以写一个 SELECT 语句来取得这些值。下面的 SQL 语句中星号 (*) 表示选择所有的列。因为没有用 WHERE 子句来限制所选的行,因此下面的 SQL 语句选择的是整个表。

SELECT * FROM COFFEES

结果是整个表的数据,如下:

COF_NAME SUP_ID PRICE SALES TOTAL

--------------- ------ ----- ----- -----

Colombian 101 7.99 0 0

French_Roast 49 8.99 0 0

Espresso 150 9.99 0 0

Colombian_Decaf 101 8.99 0 0

French_Roast_Decaf 49 9.99 0 0

如果你直接在数据库系统里输入 SQL 查询语句,你将在你的终端上看到如上的结果。当我们通过一个 Java 应用程序存取一个数据库时,正如我们马上要做的一样,我们需要检索结果以便我们能使用他们。你将在下一节看到如何实现。

这是 SELECT 语句的另一个例子,这将得到咖啡及其各自每磅单价的列表。

SELECT COF_NAME,PRICE FROM COFFEES

查询的结果集将具有如下形式:

COF_NAME PRICE

-------- ---------- -----

Colombian 7.99

French_Roast 8.99

Espresso 9.99

Colombian_Decaf 8.99

French_Roast_Decaf 9.99

上面 SELECT 语句取得了所有咖啡的名字及价格。而下面的 SELECT 语句限制那些每磅价格低于 $9.00 的咖啡才被选择。

SELECT COF_NAME,PRICE

FROM COFFEES

WHERE PRICE < 9.00

结果集将具有如下形式:

COF_NAME PRICE

-------- ------- -----

Colombian 7.99

French_Roast 8.99

Colombian Decaf 8.99

JDBC 入门 -- 开始

你需要做的第一事情是你要正确的安装。这包含下列几个步骤:

在你的计算机上安装 Java 和 JDBC

Java 数据库连接 (JDBC) 是一个标准 SQL(Structured Query Language,结构化查询语言)数据库访问接口,可以为多种关系数据库提供统一访问。JDBC(Java DataBaseConnection,Java 数据库连接) 也提供一种基准,据此可以构建更高级的工具和接口。 JDK(Java Development Kit,Java 开发工具包)软件捆绑包括 JDBC 和 JDBC-ODBC(Open DataBase Connection,开放式数据库连接)桥。这些包也可独立得到,以跟 JDK 1.0 一起使用。应该注意的是,本文的示例使用了 JDBC 2.0 接口,需要 JDK 2.0 来运行,不能在 JDK 1.1 下运行。

你的驱动程序应该有安装方法。为特定的 DBMSs 写的 JDBC 驱动程序安装时只要拷贝到你的计算机上就可以了。并不需要特殊的配置。

如果你下载的是 Solaris 或 Windows JDK1.1 版本,桥作为包 sun.jdbc.odbc 与 JDK 一起自动安装。有关安装和配置 ODBC 的信息,请咨询 ODBC 驱动程序厂商。桥无须特殊配置。有关客户机安装和配置信息,请咨询数据库厂商。

如果需要,安装数据库系统

如果你不能确认是否安装了数据库系统,你需要按照供应商的要求安装数据库。大多数用户都已经安装了数据库,可继续使用他们安装好的数据库。

配置数据库

我们假设数据库 COFFEEBREAK 已经存在。(创建一个数据库并不困难,但需要一定的权限并通常是由数据库管理员来做)你还需要在此数据库里创建本教程作为例子使用的表。我们有意限制表的大小跟及数目,以便于管理。

假设我们的数据库是在一个咖啡馆里使用, 咖啡豆按磅卖,而咖啡则以杯为单位。为了简单起见,还假定经营者只需要 2 张表,分别存放不同种类的咖啡及咖啡供应商的有关信息。

首先我们演示怎么打开一个 DBMS 连接, 及 JDBC 是怎么发送 SQL 语句到你的 DBMS。通过这些代码,我们将表明使用 JDBC 传递 SQL 语句到你的 DBMS 并处理返回的结果是非常简单的。

所有的代码在主要的几个 DBMS 产品做了测试。然而,如果你使用 JDBC-ODBC 桥来连接旧版本 ODBC 驱动程序时,可能会遇到一些兼容性问题。

有关JDBC最新的信息,有兴趣的读者可以查阅JDBC的官方网站--即JavaSoft的主页,

⒈ JavaSoft框架

JavaSoft提供三种JDBC产品组件,它们是Java开发工具包(JDK)的组成部份:JDBC驱动程序管理器、JDBC驱动程序测试工具包和JDBC-ODBC桥。

JDBC驱动程序管理器是JDBC体系结构的支柱。它实际上很小,也很简单;其主要作用是把Java应用程序连接到正确的JDBC驱动程序上,然后即退出。

JDBC驱动程序测试工具包为使JDBC驱动程序运行您的程序提供一定的可信度。只有通过JDBC驱动程序测试的驱动程序才被认为是符合JDBC标准TM的。

JDBC-ODBC桥使ODBC驱动程序可被用作JDBC驱动程序。它的实现为JDBC的快速发展提供了一条途径,其长远目标提供一种访问某些不常见的DBMS(如果对这些不常见的DBMS未实现JDBC)的方法。

⒉ JDBC驱动程序的类型

比较常见的JDBC驱动程序可分为以下四个种类:

⑴JDBC-ODBC桥加ODBC驱动程序

JavaSoft桥产品利用ODBC驱动程序提供JDBC访问。注意,必须将ODBC二进制代码(许多情况下还包括数据库客户机代码)加载到使用该驱动程序的每个客户机上。因此,这种类型的驱动程序最适合于企业网(这种网络上客户机的安装不是主要问题),或者是用Java编写的三层结构的应用程序服务器代码。

⑵本地API

这种类型的驱动程序把客户机API上的JDBC调用转换为Oracle、Sybase、Informix、DB2或其它DBMS的调用。注意,象桥驱动程序一样,这种类型的驱动程序要求将某些二进制代码加载到每台客户机上。

⑶JDBC网络纯Java驱动程序

这种驱动程序将JDBC转换为与DBMS无关的网络协议,之后这种协议又被某个服务器转换为一种DBMS协议。这种网络服务器中间件能够将它的纯Java客户机连接到多种不同的数据库上。所用的具体协议取决于提供者。通常,这是最为灵活的JDBC驱动程序。有可能所有这种解决方案的提供者都提供适合于Intranet用的产品。为b所提出的安全性、通过防火墙的访问等方面的额外要求。几家提供者正将JDBC驱动程序加到他们现有的数据库中间件产品中。

⑷本地协议纯Java驱动程序

这种类型的驱动程序将JDBC调用直接转换为DBMS所使用的网络协议。这将允许从客户机机器上直接调用DBMS服务器,是Intranet访问的一个很实用的解决方法。由于许多这样的协议都是专用的,因此数据库提供者自己将是主要来源,有几家提供者已在着手做这件事了。

据专家预计第⑶、⑷类驱动程序将成为从JDBC访问数据库的首方法。第⑴、⑵类驱动程序在直接的纯Java驱动程序还没有上市前会作为过渡方案来使用。对第⑴、⑵类驱动程序可能会有一些变种,这些变种要求有连接器,但通常这些是更加不可取的解决方案。第⑶、⑷类驱动程序提供了Java的所有优点,包括自动安装(例如,通过使用JDBC驱动程序的appletapplet来下载该驱动程序)。

⒊ JDBC驱动程序的获取

已有几十个⑴类的驱动程序,即可与Javasoft桥联合使用的ODBC驱动程序的驱动程序。有大约十多个属于种类⑵的驱动程序是以DBMS的本地API为基础编写的。只有几个属于种类⑶的驱动程序,其首批提供者是SCO、OpenHorizon、Visigenic和WebLogic。此外,JavaSoft和数据库连接的领先提供者Intersolv还合作研制了JDBC-ODBC桥和JDBC驱动程序测试工具包。

Connection 对象代表与数据库的连接。连接过程包括所执行的 SQL 语句和在该连接上所返回的结果。一个应用程序可与单个数据库有一个或多个连接,或者可与许多数据库有连接。

⒈ 打开连接

与数据库建立连接的标准方法是调用DriverManager.getConnection方法。该方法接受含有某个URL的字符串。DriverManager类(即所谓的JDBC管理层)将尝试找到可与那个URL所代表的数据库进行连接的驱动程序。DriverManager类存有已注册的Driver类的清单。当调用方法getConnection时,它将检查清单中的每个驱动程序,直到找到可与URL中指定的数据库进行连接的驱动程序为止。Driver的方法connect使用这个URL来建立实际的连接。

用户可绕过JDBC管理层直接调用Driver方法。这在以下特殊情况下将很有用:当两个驱动器可同时连接到数据库中,而用户需要明确地选用其中特定的驱动器。但一般情况下,让DriverManager类处理打开连接这种事将更为简单。

下述代码显示如何打开一个与位于URL"jdbc:odbc:wombat"的数据库的连接。所用的用户标识符为"freely",口令为"ec":

String url = "jdbc:odbc:wombat";

Connection con = DriverManager.getConnection(url, "freely", "ec");

⒉ 一般用法的URL

由于URL常引起混淆,我们将先对一般URL作简单说明,然后再讨论JDBCURL。URL(统一资源定位符)提供在Internet上定位资源所需的信息。可将它想象为一个地址。URL的第一部份指定了访问信息所用的协议,后面总是跟着冒号。常用的协议有"ftp"(代表"文件传输协议")和"http"(代表"超文本传输协议")。如果协议是"file",表示资源是在某个本地文件系统上而非在Internet上(下例用于表示我们所描述的部分;它并非URL的组成部分)。

URL的其余部份(冒号后面的)给出了数据资源所处位置的有关信息。如果协议是file,则URL的其余部份是文件的路径。对于ftp和http协议,URL的其余部份标识了主机并可选地给出某个更详尽的地址路径。例如,以下是JavaSoft主页的URL。该URL只标识了主机:从该主页开始浏览,就可以进到许多其它的网页中,其中之一就是JDBC主页。

⒊ JDBC URL

JDBC URL提供了一种标识数据库的方法,可以使相应的驱动程序能识别该数据库并与之建立连接。实际上,驱动程序编程员将决定用什么JDBC URL来标识特定的驱动程序。用户不必关心如何来形成JDBC URL;他们只须使用与所用的驱动程序一起提供的URL即可。JDBC的作用是提供某些约定,驱动程序编程员在构造他们的JDBC URL时应该遵循这些约定。

由于JDBC URL要与各种不同的驱动程序一起使用,因此这些约定应非常灵活。首先,它们应允许不同的驱动程序使用不同的方案来命名数据库。例如,odbc子协议允许(但并不是要求)URL含有属性值。

其次,JDBC URL应允许驱动程序编程员将一切所需的信息编入其中。这样就可以让要与给定数据库对话的applet打开数据库连接,而无须要求用户去做任何系统管理工作。

最后,JDBC URL应允许某种程度的间接性。也就是说,JDBC URL可指向逻辑主机或数据库名,而这种逻辑主机或数据库名将由网络命名系统动态地转换为实际的名称。这可以使系统管理员不必将特定主机声明为JDBC名称的一部份。网络命名服务(例如DNS、NIS和DCE)有多种,而对于使用哪种命名服务并无限制。

JDBC URL的标准语法如下所示。它由三部分组成,各部分间用冒号分隔:

jdbc:<;协议:子协议:子名称>  JDBC URL的三个部分可分解如下:

⑴jdbc协议:JDBC URL中的协议总是jdbc。

⑵<;子协议>;:驱动程序名或数据库连接机制(这种机制可由一个或多个驱动程序支持)的名称。子协议名的典型示例是"odbc",该名称是为用于指定ODBC风格的数据资源名称的URL专门保留的。例如,为了通过JDBC-ODBC桥来访问某个数据库,可以用如下所示的URL:jdbc:odbc:book。本例中,子协议为"odbc",子名称"book"是本地ODBC数据资源。如果要用网络命名服务(这样JDBC URL中的数据库名称不必是实际名称),则命名服务可以作为子协议。例如,可用如下所示的URL:jdbc:dcenaming:accounts。本例中,该URL指定了本地DCE命名服务应该将数据库名称"accounts"解析为更为具体的可用于连接真实数据库的名称。

⑶<;子名称>;:种标识数据库的方法。子名称可以依不同的子协议而变化。它还可以有子名称的子名称(含有驱动程序编程员所选的任何内部语法)。使用子名称的目的是为定位数据库提供足够的信息。前例中,因为ODBC将提供其余部份的信息,因此用"book"就已足够。然而,位于远程服务器上的数据库需要更多的信息。例如,如果数据库是通过Internet来访问的,则在JDBC URL中应将网络地址作为子名称的一部份包括进去,且必须遵循如下所示的标准URL命名约定://主机名:端口/子协议。

假设"dbnet"是个用于将某个主机连接到Internet上的协议,则JDBC URL应为:jdbc:dbnet://wombat:356/fred。

⒋ "odbc"子协议

子协议odbc是一种特殊情况。它是为用于指定ODBC风格的数据资源名称的URL而保留的,并具有下列特性:允许在子名称(数据资源名称)后面指定任意多个属性值。odbc子协议的完整语法为:

jdbc:odbc:<;数据资源名称>;【;<;属性名>=<;属性值>;】,因此,以下都是合法的jdbc:odbc名称:

jdbc:odbc:qeor7

jdbc:odbc:wombat

jdbc:odbc:wombat;CacheSize=20;ExtensionCase=LOWER

jdbc:odbc:qeora;UID=kgh;PWD=fooey

⒌ 注??称以将之用作JDBC URL的子协议名。当DriverManager类将此名称加到已注册的驱动程序清单中时,为之保留该名称的驱动程序应能识别该名称并与它所标识的数据库建立连接。例如,odbc是为JDBC-ODBC桥而保留的。假设有个Miracle公司,它可能会将"miracle"注册为连接到其Miracle DBMS上的JDBC驱动程序的子协议,从而使其他人都无法使用这个名称。

JavaSoft作为非正式代理负责注册JDBC子协议名称。

⒍ 发送SQL语句

连接一旦建立,就可用来向它所涉及的数据库传送SQL语句。JDBC对可被发送的SQL语句类型不加任何限制。这就提供了很大的灵活性,即允许使用特定的数据库语句或甚至于非SQL语句。然而,它要求用户自己负责确保所涉及的数据库可以处理所发送的SQL语句,否则将自食其果。例如,如果某个应用程序试图向不支持储存程序的DBMS发送储存程序调用,就会失败并将抛出异常。JDBC要求驱动程序应至少能提供ANSI SQL-2 Entry Level功能才可算是符合JDBC标准TM的。这意味着用户至少可信赖这一标准级别的功能。

JDBC提供了三个类,用于向数据库发送SQL语句。Connection接口中的三个方法可用于创建这些类的实例。下面列出这些类及其创建方法:

⑴Statement:由方法createStatement所创建。Statement对象用于发送简单的SQL语句。

⑵PreparedStatement:由方法prepareStatement所创建。PreparedStatement对象用于发送带有一个或多个输入参数(IN参数)的SQL语句。PreparedStatement拥有一组方法,用于设置IN参数的值。执行语句时,这些IN参数将被送到数据库中。PreparedStatement的实例扩展了Statement,因此它们都包括了Statement的方法。PreparedStatement对象有可能比Statement对象的效率更高,因为它已被预编译过并存放在那以供将来使用。

⑶CallableStatement:由方法prepareCall所创建。CallableStatement对象用于执行SQL储存程序─一组可通过名称来调用(就象函数的调用那样)的SQL语句。CallableStatement对象从PreparedStatement中继承了用于处理IN参数的方法,而且还增加了用于处理OUT参数和INOUT参数的方法。

不过通常来说createStatement方法用于简单的SQL语句(不带参数)、prepareStatement方法用于带一个或多个IN参数的SQL语句或经常被执行的简单SQL语句,而prepareCall方法用于调用已储存过程。

⒎ 事务

事务由一个或多个这样的语句组成:这些语句已被执行、完成并被提交或还原。当调用方法commit或rollback时,当前事务即告就结束,另一个事务随即开始。缺省情况下,新连接将处于自动提交模式。也就是说,当执行完语句后,将自动对那个语句调用commit方法。这种情况下,由于每个语句都是被单独提交的,因此一个事务只由一个语句组成。如果禁用自动提交模式,事务将要等到commit或rollback方法被显式调用时才结束,因此它将包括上一次调用commit或rollback方法以来所有执行过的语句。对于第二种情况,事务中的所有语句将作为组来提交或还原。

方法commit使SQL语句对数据库所做的任何更改成为永久性的,它还将释放事务持有的全部锁。而方法rollback将弃去那些更改。有时用户在另一个更改生效前不想让此更改生效。这可通过禁用自动提交并将两个更新组合在一个事务中来达到。如果两个更新都是成功,则调用commit方法,从而使两个更新结果成为永久性的;如果其中之一或两个更新都失败了,则调用rollback方法,以将值恢复为进行更新之前的值。

大多数JDBC驱动程序都支持事务。事实上,符合JDBC的驱动程序必须支持事务。DatabaseMetaData给出的信息描述DBMS所提供的事务支持水平。

⒏ 事务隔离级别

如果DBMS支持事务处理,它必须有某种途径来管理两个事务同时对一个数据库进行操作时可能发生的冲突。用户可指定事务隔离级别,以指明DBMS应该花多大精力来解决潜在冲突。例如,当事务更改了某个值而第二个事务却在该更改被提交或还原前读取该值时该怎么办。

假设第一个事务被还原后,第二个事务所读取的更改值将是无效的,那么是否可允许这种冲突?JDBC用户可用以下代码来指示DBMS允许在值被提交前读取该值("dirty读取"),其中con是当前连接:

con.setTransactionIsolation(TRANSACTION_READ_UNCOMMITTED);

事务隔离级别越高,为避免冲突所花的精力也就越多。Connection接口定义了五级,其中最低级别指定了根本就不支持事务,而最高级别则指定当事务在对某个数据库进行操作时,任何其它事务不得对那个事务正在读取的数据进行任何更改。通常,隔离级别越高,应用程序执行的速度也就越慢(由于用于锁定的资源耗费增加了,而用户间的并发操作减少了)。在决定采用什么隔离级别时,开发人员必须在性能需求和数据一致性需求之间进行权衡。当然,实际所能支持的级别取决于所涉及的DBMS的功能。

当创建Connection对象时,其事务隔离级别取决于驱动程序,但通常是所涉及的数据库的缺省值。用户可通过调用setIsolationLevel方法来更改事务隔离级别。新的级别将在该连接过程的剩余时间内生效。要想只改变一个事务的事务隔离级别,必须在该事务开始前进行设置,并在该事务结束后进行复位。我们不提倡在事务的中途对事务隔离级别进行更改,因为这将立即触发commit方法的调用,使在此之前所作的任何更改变成永久性的。

DriverManager 类是 JDBC 的管理层,作用于用户和驱动程序之间。它跟踪可用的驱动程序,并在数据库和相应驱动程序之间建立连接。另外,DriverManager类也处理诸如驱动程序登录时间限制及登录和跟踪消息的显示等事务。

对于简单的应用程序,一般程序员需要在此类中直接使用的唯一方法是DriverManager.getConnection。正如名称所示,该方法将建立与数据库的连接。JDBC允许用户调用DriverManager的方法getDriver、getDrivers和registerDriver及Driver的方法connect。但多数情况下,让DriverManager类管理建立连接的细节为上策。

⒈ 跟踪可用驱动程序

⒉ 建立连接

ResultSet包含符合SQL语句中条件的所有行,并且它通过一套get方法(这些get方法可以访问当前行中的不同列)提供了对这些行中数据的访问。ResultSet.next方法用于移动到ResultSet中的下一行,使下一行成为当前行。

⒈ 行和光标

ResultSet维护指向其当前数据行的光标。每调用一次next方法,光标向下移动一行。

⒉ 列

方法getXXX提供了获取当前行中某列值的途径。在每一行内,可按任何次序获取列值。但为了保证可移植性,应该从左至右获取列值,并且一次性地读取列值。

⒊ 数据类型和转换

对于getXXX方法,JDBC驱动程序试图将基本数据转换成指定Java类型,

⒋ 对非常大的行值使用流

ResultSet可以获取任意大的LONGVARBINARY或LONGVARCHAR数据。方法getBytes和getString将数据返回为大的块(最大为Statement.getMaxFieldSize的返回值)。

⒌ NULL结果值

要确定给定结果值是否是JDBC NULL,必须先读取该列,然后使用ResultSet.wasNull

方法检查该次读取是否返回JDBC NULL。

⒍ 可选结果集或多结果集

通常使用executeQuery(它返回单个ResultSet)或executeUpdate(它可用于任何数据库修改语句,并返回更新行数)可执行SQL语句。但有些情况下,应用程序在执行语句之前不知道该语句是否返回结果集。此外,有些已存储过程可能返回几个不同的结果集和/或更新计数。

用户不必关闭ResultSet;当产生它的Statement关闭、重新执行或用于从多结果序列中获取下一个结果时,该ResultSet将被Statement自动关闭。

本实例中对数据库连接和执行SQL语句等通用数据库操作进行了封装,通过实现DBConnBean和DBQueryBean两个JavaBean来完成上述功能。其中DBConnBean负责Java应用程序和数据库的连接;DBQueryBean提供了一组执行标准SQL的功能,可以实现标准SQL完成的所有功能。

本实例中主要出现了三个数据库表,表名和字段分别如下所示:

计划采购表:jhcg_table

字段名称 中文名称 类型 长度

Goods_no 物品编号 vchar 10

Goods_name 物品名称 Vchar 50

Amount 采购数量 Int

Price 采购单价 float

Gold 币种 Vchar 15

Units 单位 Vchar 10

Date 时间 Date

Remark 备注 vchar 100

库存统计表:kctj_table

字段名称 中文名称 类型 长度

Goods_no 物品编号 Vchar 10

Goods_name 物品名称 Vchar 50

amount 库存数量 Int

Date 时间 Date

remark 备注 Vchar 100

实际采购表:sjcg_table

字段名称 中文名称 类型 长度

Goods_no 物品编号 Vchar 10

Goods_name 物品名称 Vchar 50

Amount 采购数量 Int

Price Price 采购单价 Float

Gold 币种 Vchar 15

Units 采购单位 Vchar 10

Date 时间 Date

Remark 备注 vchar 100

其中业务逻辑非常简单,即根据计划采购表和库存统计表生成实际采购表。同时,对各表完成数据库的增、删、改、查等通用操作。

① 插入操作

完成对数据库表的记录插入功能,其中计划采购表的插入主页面(insert_jhcg.htm)为:

insert_jhcg.htm将用户输入传送给demo_insert_jhcg.jsp,完成插入操作。

② 查询操作

该查询主页面主要提供对三个数据库表的条件查询功能,

query.htm将用户选择查询的数据库表和查询条件发送给demo_query.jsp,由jsp文件完成数据库查询操作和查询结果集的返回及显示,

③ 生成实际采购表

生成数据库表是一个隐式操作,程序根据计划采购表和库存统计表的相应字段生成实际采购表,不需要用户的任何输入,

上述的开发工具综合应用介绍了基于Java开发电子商务应用系统的全过程,包括应用开发平台搭建、业务流程分析、JavaBean封装和JSP开发等内容,其中JSP开发中涉及到了通用SQL(查询和插入数据库表)和游标操作(生成实际采购表),基本可以完成任何网络数据库应用的需求。本实例基本上可以将前面介绍的基于Java的电子商务开发技术串接起来,指导读者进行电子商务应用开发。

分页显示是Web数据库应用中经常需要遇到的问题,当用户的数据库查询结果远远超过了计算机屏幕的显示能力的时候,我们该如何合理的将数据呈现给用户呢?答案就是数据库分页显示,可以完美的解决上述问题。下面是一个数据库分页操作的通用实例,对任何数据库平台上的分页功能都有很好的借鉴意义。

相关词汇