JDBC 驱动开发准则 (Driver GuideLines)

JDBC 驱动开发准则( Driver Guidelines

译者序( Preface

该准则来源“ <<JDBC API Tutorial And Reference,Third Edition>> 中的附录 A For Driver Writers ”。希望能够对大家有所帮助,尤其是开发数据库驱动的,希望能有一个整体的开发概念,根据准则中的描述,深入到每个开发要点和细节,结合实际的 DBMS 作出正确的选择。

作者: Maydene Fisher,Jon Ellis,Jonathan Bruce                译者:汤泳( Miker.Tang

由于时间的仓促和翻译的不到位,有许多地方值得推敲,请大家及时反馈 tangyong@fnst.com.cn ,谢谢!

对所有驱动的要求

这部分为 JDBC 驱动的标准实现提供了要求。一般地,不要求 JDBC 驱动提供数据库管理系统不支持的特性。

准则( Guidelines

以下的准则适用于 JDBC 1.0,JDBC 2.0 JDBC 3.0 API 的实现。

Ø         JDBC API 需要支持 SQL92 标准指定的 SQL 命令。参见“ 支持 SQL92扩展标准 ”以获取更多的细节。

Ø         驱动必须支持 escape syntax 。“ 支持 SQL92 扩展标准 ”给予了 escape syntax 更多的细节。

Ø         驱动必须支持事务。

Ø         驱动应该提供对潜在数据源实现的每个特性的访问能力,包括 JDBC API 扩展的特性。当不能支持某个特性时,相应的方法要抛出 SQLException 。目的是对于使用 JDBC API 的应用程序能够访问同样的特性集。

Ø         如果一个 DatabaseMetaData 的方法暗示了支持某个给定的特性,那么就像在相关的规范中描述的那样,通过标准的语法和语义必须要支持。这也许需要驱动提供到数据源原生 API 或不同于标准的 SQL 语义的映射。

Ø         如果支持某个特性,相关的 metadata 方法必须要实现。例如:如果 JDBC API 的实现支持 RowSet 接口,那么也要实现 RowSetMetaData 接口。

Ø         如果不支持某个特性,相应的 DatabaseMetaData 中的方法也必须要给出说明。试图访问不支持的特性将导致 SQLException 被抛出。

 

在接口中实现方法

       JDBC 1.0 API 的接口中所有的方法必须要实现以便至少支持 ANSI SQL 92 X/Open SQL CLI JDBC 2.0 API JDBC 3.0 API 必须要实现来支持 ANSI SQL 92,ANSI SQL 99 相关的部分和 X/Open SQL CLI

       除基本的标准以外,如果 DBMS 不支持某个特性,驱动也不必支持。例如:如果 DBMS 不支持 SQL 99 中的数据类型,那么实现支持这些新的类型( Array,Blob,Clob,Ref,SQLData,SQLInput,SQLOutput Struct )的接口就是可选的。或者,如果 DBMS 不支持某个可选包的特性,诸如 connection pooling ,那么支持 connection pooling Connection Event,ConnectionEventListener,ConnectionPoolDataSource,PooledConnection )的接口就是可选的。如果某个方法支持 DBMS 不包括的特性,那么该方法的实现将抛出 SQLException

       Metadata 接口应该被完全实现。 DatabaseMetaData 接口的目的是告诉用户 DBMS 支持哪些特性和不支持哪些特性,因此每个方法都要实现。同样地, ResultSetMetaData ParameterMetaData 接口要完全被实现。提供 javax.sql.RowSet 实现的驱动提供商也应该提供一个 javax.sql.RowSetMetaData 接口的完全实现。


注意:
JDBC 可选包中的接口已经是 JDBC 3.0 API 的一部分,并且 JDBC 驱动应该实现来作为核心的 JDBC API 。但是, RowSet 接口和支持它的接口并不包含在里面,因为它们可以实现在 JDBC API 的上层,这样就不作为驱动实现的一部分了。 支持分布式事务的 JDBC 驱动必须支持 XAConnection XADataSource 接口。

 

兼容 JDBC 1.0 API 的要求

为了兼容 JDBC 1.0 API ,驱动实现需要做以下:

Ø         坚持上面的准则和要求。

Ø         完全实现下列接口:

java.sql.Driver

java.sql.DatabaseMetaData 除了在 JDBC 2.0 API JDBC 3.0 API 引入的方法

java.sql.ResultSetMetaData ・除了在 JDBC 2.0 API JDBC 3.0 API 引入的方法

Ø         包括下列所需的接口:

java.sql.CallableStatement

java.sql.Connection

java.sql.PreparedStatement

java.sql.ResultSet

java.sql.Statement

兼容 JDBC 2.0 API 的要求

为了兼容 JDBC 1.0 API ,驱动实现需要做以下:

Ø         符合 JDBC 1.0 API 的要求。

Ø         完全实现 DatabaseMetaData 接口,包括在 JDBC 2.0 API 中增加的下列方法:

deletesAreDetected

getConnection

getUDTs

insertsAreDetected

othersDeletesAreVisible

othersInsertsAreVisible

othersUpdatesAreVisible

ownDeletesAreVisible

ownInsertsAreVisible

ownUpdatesAreVisible

supportsBatchUpdates

supportsResultSetConcurrency

supportsResultSetType

updatesAreDetected

 

Ø         实现下面 ResultSetMetaData 中其他的方法:

getColumnClassName

getColumnType

getColumnTypeName

兼容 JDBC 3.0 API 的要求

为了兼容 JDBC 3.0 API ,驱动实现需要做以下:

Ø         符合 JDBC 2.0 API 的要求

Ø         包括以下所需的接口:

java.sql.ParameterMetaData

java.sql.Savepoint

 

Ø         完全实现 DatabaseMetaData 接口,包括在 JDBC 3.0 API 中增加的下列方法:

supportsSavepoints

supportsNamedParameters

supportsMultipleOpenResults

supportsGetGeneratedKeys

getSuperTypes

getSuperTables

getAttributes

getResultSetHoldability

supportsResultSetHoldability

getSQLStateType

getDatabaseMajorVersion

getDatabaseMinorVersion

getJDBCmajorVersion

getJDBCMinorVersion

已经被实现的 API

下面的类和异常在 JDBC 3.0 API 中已经完全被实现了:

·         java.sql.BatchUpdateException

·         java.sql.DataTruncation

·         java.sql.Date

·         java.sql.DriverManager

·         java.sql.DriverPropertyInfo

·         java.sql.SQLException

·         java.sql.SQLPermission

·         java.sql.SQLWarning

·         java.sql.Time

·         java.sql.Timestamp

·         java.sql.Types

·         javax.sql.ConnectionEvent

·         javax.sql.RowSetEvent

其他的要求

除了满足上面列举的要求外, JDBC 驱动也必须符合下面列举的要求:

实现 Static Initializer

每个 Driver 类应该包含一个特殊的静态区域,有时被称作 Static Initializer ,当使用 DriverManager 来加载 Driver 类时, Driver 类的 Static Initializer 被调用。当加载 Driver 类时, Static Initializer 完成以下两件事:

1.  创建 Driver 类的实例。

2.  通过调用 DriverManager.registerDriver 注册新创建的 Driver 实例。

下面的代码演示了 Static Initializer

				
						  public class MyDriver implements java.sql.Driver {
				
		
				
						
								
										     static {
						
				
		
				
						
								
										        java.sql.DriverManager.registerDriver(new MyDriver());
						
				
		
				
						
								
										     }
						
				
		
				
						
								
										      . . .
						
				
				
						}

 

 

 

 

 

 

 

 

 


 

当完成以上两件事之后,用户通过调用 Class.forName Driver 类名作为参数)方法能够加载和注册 JDBC 驱动。


 注意:Static Initializer
仅仅适用使用 DriverManager 加载驱动的方式。通过 DataSource API 加载驱动不会使用 DriverManager 自动地注册,而且在实现上也不应该包含 Static Initializer DriverManager DriverPropertyInfo 类包括 Driver 接口也许在将来会被削弱。

 

支持 SQL92 扩展标准

 

 

支持 Scalar 函数

支持 Scalar 函数需要一些额外的解释。 JDBC 支持数字型,字符串型,时间型,日期型, System 和转换成 Scalar 值的函数。对于那些想要比“ Statements 中的 SQL Escape Syntax ”更多信息的人来说, X/Open Group CLI 规范提供了关于 Scalar 函数语义更多的信息。以下是这些函数的列表。

如果 DBMS 支持 Scalar 函数,驱动也应该支持。因为不同的 DBMS Scalar 函数语法上的支持会有不同,所以驱动就是或者将 Scalar 函数映射成合适的语法,或者是在驱动中直接实现这些函数。

用户通过调用 metadata 中的方法应该能发现哪些函数被支持。例如:方法 DatabaseMetaData.getNumericFunctions 应该返回一个逗号分隔的被 Open Group CLI 支持的 numeric 函数列表。类似地,方法 DatabaseMetaData.getStringFunctions 应该返回一个 string 函数列表,等等。

以下是按照种别列出的 Scalar 函数:

NUMERIC FUNCTIONS

Function Name

Function Returns

ABS(number)

Absolute value of number

ACOS(float)

Arccosine, in radians, of float

ASIN(float)

Arcsine, in radians, of float

ATAN(float)

Arctangent, in radians, of float

ATAN2(float1, float2)

Arctangent, in radians, of float2 / float1

CEILING(number)

Smallest integer >= number

COS(float)

Cosine of float radians

COT(float)

Cotangent of float radians

DEGREES(number)

Degrees in number radians

EXP(float)

Exponential function of float

FLOOR(number)

Largest integer <= number

LOG(float)

Base e logarithm of float

LOG10(float)

Base 10 logarithm of float

MOD(integer1, integer2)

Remainder for integer1 / integer2

PI()

The constant pi

POWER(number, power)

number raised to (integer) power

RADIANS(number)

Radians in number degrees

RAND(integer)

Random floating point for seed integer

ROUND(number, places)

number rounded to places places

SIGN(number)

to indicate number is < 0;

0 to indicate number is = 0;

1 to indicate number is > 0

SIN(float)

Sine of float radians

SQRT(float)

Square root of float

TAN(float)

Tangent of float radians

TRUNCATE(number, places)

number truncated to places places

 

STRING FUNCTIONS

Function Name

Function Returns

ASCII(string)

Integer representing the ASCII code value of the leftmost character in string

CHAR(code)

Character with ASCII code value code , where code is between 0 and 255

CONCAT(string1, string2)

Character string formed by appending string2 to string1 ; if a string is null, the result is DBMS-dependent

DIFFERENCE(string1, string2)

Integer indicating the difference between the values returned by the function SOUNDEX for string1 and string2

INSERT(string1, start, length, string2)

A character string formed by deleting length characters from string1 beginning at start , and inserting string2 into string1 at start

LCASE(string)

Converts all uppercase characters in string to lowercase

LEFT(string, count)

The count leftmost characters from string

LENGTH(string)

Number of characters in string , excluding trailing blanks

LOCATE(string1, string2[, start])

Position in string2 of the first occurrence of string1 , searching from the beginning of string2 ; if start is specified, the search begins from position start . 0 is returned if string2 does not contain string1 . Position 1 is the first character in string2 .

LTRIM(string)

Characters of string with leading blank spaces removed

REPEAT(string, count)

A character string formed by repeating string count times

REPLACE(string1, string2, string3)

Replaces all occurrences of string2 in string1 with string3

RIGHT(string, count)

The count rightmost characters in string

RTRIM(string)

The characters of string with no trailing blanks

SOUNDEX(string)

A character string, which is data source-dependent, representing the sound of the words in string ; this could be a four-digit SOUNDEX code, a phonetic representation of each word, etc.

SPACE(count)

A character string consisting of count spaces

SUBSTRING(string, start, length)

A character string formed by extracting length characters from string beginning at start

UCASE(string)

Converts all lowercase characters in string to uppercase

TIME and DATE FUNCTIONS

Function Name

Function Returns

CURDATE()

The current date as a date value

CURTIME()

The current local time as a time value

DAYNAME(date)

A character string representing the day component of date ; the name for the day is specific to the data source

DAYOFMONTH(date)

An integer from 1 to 31 representing the day of the month in date

DAYOFWEEK(date)

An integer from 1 to 7 representing the day of the week in date ; 1 represents Sunday

DAYOFYEAR(date)

An integer from 1 to 366 representing the day of the year in date

HOUR(time)

An integer from 0 to 23 representing the hour component of time

MINUTE(time)

An integer from 0 to 59 representing the minute component of time

MONTH(date)

An integer from 1 to 12 representing the month component of date

MONTHNAME(date)

A character string representing the month component of date ; the name for the month is specific to the data source

NOW()

A timestamp value representing the current date and time

QUARTER(date)

An integer from 1 to 4 representing the quarter in date ; 1 represents January 1 through March 31

SECOND(time)

An integer from 0 to 59 representing the second component of time

TIMESTAMPADD(interval, count, timestamp)

A timestamp calculated by adding count number of interval (s) to timestamp ; interval may be one of the following: SQL_TSI_FRAC_SECOND , SQL_TSI_SECOND , SQL_TSI_MINUTE , SQL_TSI_HOUR , SQL_TSI_DAY , SQL_TSI_WEEK , SQL_TSI_MONTH , SQL_TSI_QUARTER , or SQL_TSI_YEAR

TIMESTAMPDIFF(interval, timestamp1, timestamp2)

An integer representing the number of interval (s) by which timestamp2 is greater than timestamp1 ; interval may be one of the following: SQL_TSI_FRAC_SECOND , SQL_TSI_SECOND , SQL_TSI_MINUTE , SQL_TSI_HOUR , SQL_TSI_DAY , SQL_TSI_WEEK , SQL_TSI_MONTH , SQL_TSI_QUARTER , or SQL_TSI_YEAR

WEEK(date)

An integer from 1 to 53 representing the week of the year in date

YEAR(date)

An integer representing the year component of date

 

SYSTEM FUNCTIONS

Function Name

Function Returns

DATABASE()

Name of the database

IFNULL(expression, value)

value if expression is null ; expression if expression is not null

USER()

User name in the DBMS

CONVERSION FUNCTIONS

Function Name

Function Returns

CONVERT(value, SQLtype)

value converted to SQLtype where SQLtype may be one of the following SQL types: BIGINT , BINARY , BIT , CHAR , DATE , DECIMAL , DOUBLE , FLOAT , INTEGER , LONGVARBINARY , LONGVARCHAR , REAL , SMALLINT , TIME , TIMESTAMP , TINYINT , VARBINARY , or VARCHAR

 

提供 Positioned Updates Deletes 锁定

JDBC 3.0 核心 API position 结果集游标提供了不同的方法,因此,在结果集中很容易更新或删除一个特别的行。但是, JDBC 1.0 API 仅仅提供了简单的游标支持,这也就使得 positioned Update Delete 有点复杂。

 

       当使用 executeQuery 执行查询的时候,返回结果集且游标位于第一行记录的前面。直到结果集对象或创建该结果集的 Statement 关闭为止,游标将保持有效。如果驱动不支持游标的 position 方法,那么应用程序必须通过调用 ResultSet.getCursorName 方法来获取游标的名称。这个游标的名称能够被使用在 position Update Delete 语句中。


注意:
所有
DBMS 都支持 position Update Delete 。应用程序能够使用 DatabaseMetaData.supportsPositionedUpdate DatabaseMetaData.supportsPostionedDelete 方法来决定当前的连接是否支持。因为许多 DBMS Select 语句( in Select For Update )中都不支持“ for update ”,所以驱动必须要检查并且实现这个语义。这个语法( for update )的目的是通知生成的结果集将使用 position Update Delete 另外, JDBC 3.0 API 允许应用程序指定结果集对象的持久性( Holdability ),这就允许在事务过程中创建的结果集对象在事务被提交的生命周期以外被维护。这也意味着 JDBC 驱动必须考虑额外的锁定功能。

       当支持 position update delete 时, DBMS/Driver 必须确保被筛选的行能够被锁定以便 postion update 不会导致更新异常或是其他的并发问题。

 

 

支持多线程

java.sql javax.sql 中对象的所有操作都需要多线程的安全。它们必须能正确地处理几个线程同时调用同一个对象。换句话说,在一个线程中执行的命令不应该阻塞在另一个线程中的执行。特别地,当使用多线程时, JDBC 驱动应该能正确地操作。

一个具体使用多线程的例子是一个长时间运行的命令能够被取消。通过使用一个线程执行该命令而另一个线程能够取消掉来达到目的。

尽管在实际中能够预想决大多数 JDBC 对象将以单线程的方式被访问,但是也需要支持多线程的方式。

一些数据库的 API ,如 ODBC ,提供了异步执行 SQL 语句的机制。这就允许一个应用程序在后台开启数据库的操作,然后处理其他的工作(例如管理用户的接口)来等待后台操作的完成。

因为 Java 编程语言提供了多线程的环境,因此提供异步命令的执行似乎就没有必要了。如果想要异步地执行命令,程序开发人员能够很容易地创建一个隔离的线程。

一些驱动也许允许更多的并发执行,但是开发人员应该能够设想出完全的并发执行场景。如果该驱动需要某种形式的同步,那么驱动应该要提供。在这种情形下,唯一的不同应该是应用程序并发运行的次数会降低。

例如:在同一连接中的两个命令对象能够并发地执行,并且它们的结果集对象能够被并发地处理(从开发者的角度看)。一些驱动将完全提供这种并发能力。其他的也许执行一个命令并且在处理下个结果集之前一直等到第一个处理完成。

为截断的输入参数抛出异常

如果输入的参数被截断,那么 DataTruncation 的异常应该被抛出,参见“ Data Truncation ”,获取更多的信息。

SQL99 数据类型使用默认的行为( JDBC 2.0

 

差异性

       由于在数据库功能和语法上的差异,在驱动的实现上 JDBC 允许一些差异。数据库所使用的 SQL 也许不同。例如:对于 Outer Joins ,不同的数据库提供了不同的支持。而且,许多 SQL 特性也许在不同的数据库间存在差异。

       Java.sql..DatabaseMetaData 接口提供了许多的方法,通过使用这些方法,用户能够确切地知道当前的数据库支持哪些 SQL 特性。对于驱动开发人员来说,必须确保 DatabaseMetaData 的方法能够返回准确的信息,即 DBMS 支持哪些特性和不支持哪些特性。

处理不支持的功能

       当数据库不支持某种功能时,驱动需要作出相应的处理。例如:一些数据库不支持存储过程的 OUT 参数。在这种情形下, CallableStatement 方法中针对 OUT 参数的方法( registerOutParameter 和相应的 getter 方法)将不能应用,并且当用户调用时,要抛出 SQLException

基本属性的差异

       在一些基本的属性方面也允许有差异,例如:事务的隔离级别。当前数据库的默认属性和这些属性的范围可以通过 DatabaseMetaData 的方法获取。

增加的功能

       数据库厂商可能会增加额外的功能,这样就会创建 JDBC 类的子类来提供这些额外的功能。例如: Foobah 公司支持了 SQL99 中的 NCHAR NVCHAR 类型,该公司也许会定义一个新的 JAVA 类型 foobah.sql.FooBahType 来扩展 java.sql.Types

驱动的安全性

      

使用 SQLException 作为异常

       如果 DBMS 不支持某个功能,方法中要抛出 SQLException

       有些情形下, Java RunTimeException SQLException 也许会重叠。例如:如果一个方法希望一个参数是 java.sql.Types ,结果却提供了其他的类型,那么, IllegalArgumentException SQLException。这样,推荐抛出SQLException,因为那将给予JDBC更多对Error的控制。

实现的建议

预检索行记录

 

提供“ Finalize ”方法

 

避免实现上的依赖

 

2.

实现 Connection Statement Pooling

在数据库应用程序中获取数据源的连接是一个更加昂贵的操作。因此,为了重用物理连接,实现池化连接的机制能够在性能上提供利益。 JDBC API 提供了一个类( ConnectionEvent )和三个接口( ConnectionEventListener ConnectionPoolDataSource PooledConnection )来作为连接池的实现策略。

       这些 API 决定了连接池如果工作的一般的准则,但是并没有提出连接池如何实现的具体细节。而且, JDBC 3.0 规范并没有定义在何处实现,留出了很大的实现自由。典型地,一个应用程序服务器将实现连接池和分布式事务的管理。驱动提供商会实现 DataSource ConnectionPoolDataSource 接口以便它们能和实现连接池的 J2EE 应用程序服务器协同工作。如果一个 JDBC 驱动包含了对连接池管理的实现,那么它应该提供一种方式,使得能够关闭驱动的实现。这样,应用程序能够选择使用应用程序服务器的实现,这样可以防止建立两个连接池。

        类似地,重用PreparedStatement对象能够增强性能,尤其当prepared statement很大并且要被使用多次的时候。驱动和DBMS也许会花费很多的资源来预编译(原文:precompilingStatement并且为了执行来准备一个策略,因此为Statement准备一次而不是多次是更加地有效。当创建Statements的连接被池化的时候,Statements也许会被池化。JDBC 3.0规范为ConnectionPoolDataSource增加了一些属性,这些属性能够创建Statement Pool的初始大小,和在池中被维护的Statement的最小数目,等等。这些属性在实现中被设置,并且不是暴露给应用程序开发人员的API一部分。从应用程序开发人员的视角考虑,对于Statement Pooling没有新的API

实现连接池和 Statement Pooling 必须对用户完全透明。一个例外是驱动应该有关闭自己对连接池实现的能力,以便使用应用程序服务器的实现。应用程序能够透明地创建,使用和关闭连接,不管是否使用了连接池。同样地,应用程序每次创建新的 PreparedStatement 对象的方式也要透明。唯一的不同是如果程序员知道连接池有效,那么他 / 她也许会更好地使用 prepared statements 。但是,一般地,在性能地改善上应用程序会开启使用连接池和 Statement Pooling

JDBC 测试套件

    驱动提供商通过使用JDBC测试套件能够测试它们的驱动是否和J2EE平台兼容。有两个版本:

·         JDBC Test Suite 1.2.1 : tests for conformance with the JDBC 2.0 API

·         JDBC Test Suite 1.3.1 : tests for conformance with the JDBC 3.0 API

这些测试套件覆盖了经过兼容J2EE测试的驱动功能。它们是免费地并且可以从以下网址下载:

http://java.sun.com/products/jdbc/download.html#jdbctestsuite

    如何安装和运行测试套件的文档在以下的网址:

http://java.sun.com/products/jdbc/jdbctestsuite-1_3_1.html

通过测试套件暗示了一个驱动是兼容其他符合J2EE规范的产品,但是并不意味这个驱动能够被标记兼容J2EE。驱动必须要通过一个外部的测试组织来测试是兼容的。完全的驱动认证过程的说明在如下的网址:

http://java.sun.com/products/jdbc/certification.html

The JDBC web pages maintain a database of JDBC drivers, which users can search to find drivers that satisfy their requirements. Search criteria include the type of driver, which versions of the JDBC Specification are supported, and which drivers have been certified to be compatible with the J2EE platform. The database is maintained at

http://java.sun.com/products/jdbc/drivers.html

Drivers may have themselves listed in the database by filling out the submission form at

http://java.sun.com/products/jdbc/add_driver.html

Connectors (连接器)

J2EE 平台上开发应用程序将几乎总想使用 JDBC API 起访问一个或更多 DBMS 。因此,对于驱动提供商来说,能够很容易地将 JDBC 驱动连接到 J2EE 应用程序服务器是件很有趣的事。

J2EE 连接器的架构

       J2EE 连接器架构 1.0 规范和 1.5 规范提供了一个框架,能够以一种可插拔( pluggable )的方式连接 J2EE 应用程序服务器到额外的资源,例如: DBMS 。完成这一功能的软件被称作资源适配器( Resource Adapter ),或者叫 Connector

       连接器架构的核心是一组契约( Contracts )。满足这些契约的驱动实现将能够插入到任何满足这些契约的 J2EE 应用程序服务器中。服务提供接口( SPI )契约定义了 J2EE 服务器和资源适配器必须实现的内容,以下是需要实现的领域:

Ø         事务管理( Transaction management

Ø         连接池管理( Connection pool management

Ø         安全性( Security

以下的接口描述了和上述契约等价的服务:

Ø         数据源(DataSource)

Ø         池化的数据源(ConnectionPoolDataSource)

Ø         支持分布式事务的数据源(XADataSource)

DataSource ConnectionPoolDataSource 接口描述了涉及连接池相关的服务。 XADataSource 接口描述涉及分布式事务相关的服务。 JDBC 并没有提供与安全性契约相关的 API ,因为认证总是要包含用户名和密码。

       为了使用连接器系统提供的的契约,驱动提供商有不同的选择:

Ø         写一系列的类,用来包装( Wrap JDBC 驱动并且实现连接器的契约。构建这些包装器相当地直接,并且应该允许提供商足够快地提供资源适配器,以便当应用程序服务器提供商已经实现了连接器契约时能够有用。

Ø         直接实现连接器契约。这样将避免包装带来的负担,但是实现将会更加地耗时和耗力。但是,这是一个长期的选择。

Ø         使用 JDBC 连接器实现。相关的信息可以从以下网址下载:

 

http://java.sun.com/products/jdbc/related.html

      

       JDBC 3.0 规范,章节 19.3 给出了以连接器资源包( RAR )文件格式包裹 JDBC 驱动的细节。下载相关的文档和 RAR 文件解释了 JDBC 连接器如何地工作并且如何地部署它。厂商将会发现使用 SPI RAR 文件非常地容易因为它们不必在驱动实现中改变任何的代码。

    The JDBC Connector download includes common client interface (CCI) RAR files as well as SPI RAR files, but they are included more to show what the CCI approach looks like than anything else. Driver vendors will more likely use the SPI RAR files because they make it possible for users to use the JDBC API just as they have always done. The overview document in the JDBC Connector download gives more complete information.

 

posted on 2006-12-29 18:29 会飞的鱼 阅读(1145) 评论(1)  编辑  收藏 所属分类: JDBC 驱动开发

评论

# re: JDBC 驱动开发准则 (Driver GuideLines) 2007-01-08 16:02 你最亲爱的老婆

我是不是也该弄篇论文在我的BLOG上啊,这样似乎会显得比较有深度啊...  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航:
 
<2007年1月>
31123456
78910111213
14151617181920
21222324252627
28293031123
45678910

导航

统计

常用链接

留言簿(2)

随笔分类

随笔档案

文章分类

文章档案

相册

友情链接

开源链接

搜索

最新评论

阅读排行榜

评论排行榜