JDBC 驱动开发准则_第1页
JDBC 驱动开发准则_第2页
JDBC 驱动开发准则_第3页
JDBC 驱动开发准则_第4页
JDBC 驱动开发准则_第5页
已阅读5页,还剩8页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、JDBC 驱动开发准则该准则来源“ <<JDBC API Tutorial And Reference,Third Edition>> 中的附录 A : For Driver Writers ”。希望能够对大家有所帮助,尤其是开发数据库驱动的,希望能有一个整体的开发概念,根据准则中的描述,深入到每个开发要点和细节,结合实际的 DBMS 作出正确的选择。作者: Maydene Fisher,Jon Ellis,Jonathan Bruce 译者:汤泳( Miker.Tang )由于时间的仓促和翻译的不到位,有许多地方值得推敲,请大家及时反馈 ,谢谢!对所有驱动的要求这部分

2、为 JDBC 驱动的标准实现提供了要求。一般地,不要求 JDBC 驱动提供数据库管理系统不支持的特性。准则( Guidelines )以下的准则适用于 JDBC 1.0,JDBC 2.0 和 JDBC 3.0 API 的实现。Ø JDBC API 需要支持 SQL92 标准指定的 SQL 命令。参见“ 支持 SQL92扩展标准”以获取更多的细节。Ø 驱动必须支持 escape syntax 。“ 支持 SQL92 扩展标准”给予了 escape syntax 更多的细节。Ø 驱动必须支持事务。Ø 驱动应该提供对潜在数据源实现的每个特性的访问能力,包括 J

3、DBC API 扩展的特性。当不能支持某个特性时,相应的方法要抛出 SQLException 。目的是对于使用 JDBC API 的应用程序能够访问同样的特性集。Ø 如果一个 DatabaseMetaData 的方法暗示了支持某个给定的特性,那么就像在相关的规范中描述的那样,通过标准的语法和语义必须要支持。这也许需要驱动提供到数据源原生 API 或不同于标准的 SQL 语义的映射。Ø 如果支持某个特性,相关的 metadata 方法必须要实现。例如:如果 JDBC API 的实现支持 RowSet 接口,那么也要实现 RowSetMetaData 接口。Ø 如果不

4、支持某个特性,相应的 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 中的数据类型,那么实现支持这

5、些新的类型( Array,Blob,Clob,Ref,SQLData,SQLInput,SQLOutput 和 Struct )的接口就是可选的。或者,如果 DBMS 不支持某个可选包的特性,诸如 connection pooling ,那么支持 connection pooling ( Connection Event,ConnectionEventListener,ConnectionPoolDataSource,PooledConnection )的接口就是可选的。如果某个方法支持 DBMS 不包括的特性,那么该方法的实现将抛出 SQLException 。 Metadata接口应该被完

6、全实现。 DatabaseMetaData 接口的目的是告诉用户 DBMS 支持哪些特性和不支持哪些特性,因此每个方法都要实现。同样地, ResultSetMetaData 和 ParameterMetaData 接口要完全被实现。提供 javax.sql.RowSet 实现的驱动提供商也应该提供一个 javax.sql.RowSetMetaData 接口的完全实现。注意:在 JDBC 可选包中的接口已经是 JDBC 3.0 API 的一部分,并且 JDBC 驱动应该实现来作为核心的 JDBC API 。但是, RowSet 接口和支持它的接口并不包含在里面,因为它们可以实现在 JDBC AP

7、I 的上层,这样就不作为驱动实现的一部分了。 支持分布式事务的 JDBC 驱动必须支持 XAConnection 和 XADataSource 接口。 兼容 JDBC 1.0 API 的要求为了兼容 JDBC 1.0 API ,驱动实现需要做以下:Ø 坚持上面的准则和要求。Ø 完全实现下列接口:java.sql.Driverjava.sql.DatabaseMetaData 除了在 JDBC 2.0 API 或 JDBC 3.0 API 引入的方法java.sql.ResultSetMetaData除了在 JDBC 2.0 API 或 JDBC 3.0 API 引入的方法&

8、#216; 包括下列所需的接口: 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 中增加的下列方法:deletesAreDetectedgetConnectiongetUDTsi

9、nsertsAreDetectedothersDeletesAreVisibleothersInsertsAreVisibleothersUpdatesAreVisibleownDeletesAreVisibleownInsertsAreVisibleownUpdatesAreVisiblesupportsBatchUpdatessupportsResultSetConcurrencysupportsResultSetTypeupdatesAreDetected Ø 实现下面 ResultSetMetaData 中其他的方法: getColumnClassName getColumn

10、Type getColumnTypeName兼容 JDBC 3.0 API 的要求为了兼容 JDBC 3.0 API ,驱动实现需要做以下:Ø 符合 JDBC 2.0 API 的要求Ø 包括以下所需的接口:java.sql.ParameterMetaDatajava.sql.Savepoint Ø 完全实现 DatabaseMetaData 接口,包括在 JDBC 3.0 API 中增加的下列方法:supportsSavepointssupportsNamedParameterssupportsMultipleOpenResultssupportsGetGener

11、atedKeysgetSuperTypesgetSuperTablesgetAttributesgetResultSetHoldabilitysupportsResultSetHoldabilitygetSQLStateTypegetDatabaseMajorVersiongetDatabaseMinorVersiongetJDBCmajorVersiongetJDBCMinorVersion已经被实现的 API下面的类和异常在 JDBC 3.0 API 中已经完全被实现了:· java.sql.BatchUpdateException· java.sql.DataTrun

12、cation· 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其他

13、的要求除了满足上面列举的要求外, JDBC 驱动也必须符合下面列举的要求:实现 Static Initializer每个 Driver 类应该包含一个特殊的静态区域,有时被称作 Static Initializer ,当使用 DriverManager 来加载 Driver 类时, Driver 类的 Static Initializer 被调用。当加载 Driver 类时, Static Initializer 完成以下两件事:1 创建 Driver 类的实例。2 通过调用 DriverManager.registerDriver 注册新创建的 Driver 实例。下面的代码演示了 Stat

14、ic 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 自动地注册,而且

15、在实现上也不应该包含 Static Initializer 。 DriverManager 和 DriverPropertyInfo 类包括 Driver 接口也许在将来会被削弱。 支持 SQL92 扩展标准 支持 Scalar 函数支持 Scalar 函数需要一些额外的解释。 JDBC 支持数字型,字符串型,时间型,日期型, System 和转换成 Scalar 值的函数。对于那些想要比“ Statements 中的 SQL Escape Syntax ”更多信息的人来说, X/Open Group CLI 规范提供了关于 Scalar 函数语义更多的信息。以下是这些函数的列表。如果 DBM

16、S 支持 Scalar 函数,驱动也应该支持。因为不同的 DBMS 对 Scalar 函数语法上的支持会有不同,所以驱动就是或者将 Scalar 函数映射成合适的语法,或者是在驱动中直接实现这些函数。用户通过调用 metadata 中的方法应该能发现哪些函数被支持。例如:方法 DatabaseMetaData.getNumericFunctions 应该返回一个逗号分隔的被 Open Group CLI 支持的 numeric 函数列表。类似地,方法 DatabaseMetaData.getStringFunctions 应该返回一个 string 函数列表,等等。以下是按照种别列出的 Sca

17、lar 函数:NUMERIC FUNCTIONSFunction NameFunction ReturnsABS(number)Absolute value of numberACOS(float)Arccosine, in radians, of floatASIN(float)Arcsine, in radians, of floatATAN(float)Arctangent, in radians, of floatATAN2(float1, float2)Arctangent, in radians, of float2/ float1CEILING(number)Smallest i

18、nteger >= numberCOS(float)Cosine of floatradiansCOT(float)Cotangent of floatradiansDEGREES(number)Degrees in numberradiansEXP(float)Exponential function of floatFLOOR(number)Largest integer <= numberLOG(float)Base e logarithm of floatLOG10(float)Base 10 logarithm of floatMOD(integer1, integer2

19、)Remainder for integer1/ integer2PI()The constant piPOWER(number, power)numberraised to (integer) powerRADIANS(number)Radians in numberdegreesRAND(integer)Random floating point for seed integerROUND(number, places)numberrounded to placesplacesSIGN(number) to indicate numberis < 0;0 to indicate nu

20、mberis = 0;1 to indicate numberis > 0SIN(float)Sine of floatradiansSQRT(float)Square root of floatTAN(float)Tangent of floatradiansTRUNCATE(number, places)numbertruncated to placesplaces STRING FUNCTIONSFunction NameFunction ReturnsASCII(string)Integer representing the ASCII code value of the lef

21、tmost character in stringCHAR(code)Character with ASCII code value code, where codeis between 0 and 255CONCAT(string1, string2)Character string formed by appending string2to string1; if a string is null, the result is DBMS-dependentDIFFERENCE(string1, string2)Integer indicating the difference betwee

22、n the values returned by the function SOUNDEXfor string1and string2INSERT(string1, start, length, string2)A character string formed by deleting lengthcharacters from string1beginning at start, and inserting string2into string1at startLCASE(string)Converts all uppercase characters in stringto lowerca

23、seLEFT(string, count)The countleftmost characters from stringLENGTH(string)Number of characters in string, excluding trailing blanksLOCATE(string1, string2, start)Position in string2of the first occurrence of string1, searching from the beginning of string2; if startis specified, the search begins f

24、rom position start. 0 is returned if string2does not contain string1. Position 1 is the first character in string2.LTRIM(string)Characters of stringwith leading blank spaces removedREPEAT(string, count)A character string formed by repeating string counttimesREPLACE(string1, string2, string3)Replaces

25、 all occurrences of string2in string1with string3RIGHT(string, count)The countrightmost characters in stringRTRIM(string)The characters of string with no trailing blanksSOUNDEX(string)A character string, which is data source-dependent, representing the sound of the words in string; this could be a f

26、our-digit SOUNDEX code, a phonetic representation of each word, etc.SPACE(count)A character string consisting of countspacesSUBSTRING(string, start, length)A character string formed by extracting lengthcharacters from stringbeginning at startUCASE(string)Converts all lowercase characters in stringto

27、 uppercaseTIME and DATE FUNCTIONSFunction NameFunction ReturnsCURDATE()The current date as a date valueCURTIME()The current local time as a time valueDAYNAME(date)A character string representing the day component of date; the name for the day is specific to the data sourceDAYOFMONTH(date)An integer

28、from 1 to 31 representing the day of the month in dateDAYOFWEEK(date)An integer from 1 to 7 representing the day of the week in date; 1 represents SundayDAYOFYEAR(date)An integer from 1 to 366 representing the day of the year in dateHOUR(time)An integer from 0 to 23 representing the hour component o

29、f timeMINUTE(time)An integer from 0 to 59 representing the minute component of timeMONTH(date)An integer from 1 to 12 representing the month component of dateMONTHNAME(date)A character string representing the month component of date; the name for the month is specific to the data sourceNOW()A timest

30、amp value representing the current date and timeQUARTER(date)An integer from 1 to 4 representing the quarter in date; 1 represents January 1 through March 31SECOND(time)An integer from 0 to 59 representing the second component of timeTIMESTAMPADD(interval, count, timestamp)A timestamp calculated by

31、adding countnumber of interval(s) to timestamp; intervalmay 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_YEARTIMESTAMPDIFF(interval, timestamp1, timestamp2)An integer representing the

32、 number of interval(s) by which timestamp2is greater than timestamp1; intervalmay 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_YEARWEEK(date)An integer from 1 to 53 representing the w

33、eek of the year in dateYEAR(date)An integer representing the year component of date SYSTEM FUNCTIONSFunction NameFunction ReturnsDATABASE()Name of the databaseIFNULL(expression, value)valueif expressionis null ; expressionif expressionis not nullUSER()User name in the DBMSCONVERSION FUNCTIONSFunctio

34、n NameFunction ReturnsCONVERT(value, SQLtype)valueconverted to SQLtypewhere SQLtypemay 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 Update

35、s 和 Deletes 锁定JDBC 3.0 核心 API 为 position 结果集游标提供了不同的方法,因此,在结果集中很容易更新或删除一个特别的行。但是, JDBC 1.0 API 仅仅提供了简单的游标支持,这也就使得 positioned Update 或 Delete 有点复杂。 当使用 executeQuery 执行查询的时候,返回结果集且游标位于第一行记录的前面。直到结果集对象或创建该结果集的 Statement 关闭为止,游标将保持有效。如果驱动不支持游标的 position 方法,那么应用程序必须通过调用 ResultSet.getCursorName 方法来获取游标的名称

36、。这个游标的名称能够被使用在 position Update 或 Delete 语句中。 注意:所有 DBMS 都支持 position Update 和 Delete 。应用程序能够使用 DatabaseMetaData.supportsPositionedUpdate 和 DatabaseMetaData.supportsPostionedDelete 方法来决定当前的连接是否支持。因为许多 DBMS 在 Select 语句( in Select For Update )中都不支持“ for update ”,所以驱动必须要检查并且实现这个语义。这个语法( for update )的目的是

37、通知生成的结果集将使用 position Update 和 Delete 。 另外, JDBC 3.0 API 允许应用程序指定结果集对象的持久性( Holdability ),这就允许在事务过程中创建的结果集对象在事务被提交的生命周期以外被维护。这也意味着 JDBC 驱动必须考虑额外的锁定功能。 当支持 position update 和 delete 时, DBMS/Driver 必须确保被筛选的行能够被锁定以便 postion update 不会导致更新异常或是其他的并发问题。 支持多线程java.sql 和 javax.sql 中对象的所有操作都需要多线程的安全。它们必须能正确地处理几

38、个线程同时调用同一个对象。换句话说,在一个线程中执行的命令不应该阻塞在另一个线程中的执行。特别地,当使用多线程时, JDBC 驱动应该能正确地操作。一个具体使用多线程的例子是一个长时间运行的命令能够被取消。通过使用一个线程执行该命令而另一个线程能够取消掉来达到目的。尽管在实际中能够预想决大多数 JDBC 对象将以单线程的方式被访问,但是也需要支持多线程的方式。一些数据库的 API ,如 ODBC ,提供了异步执行 SQL 语句的机制。这就允许一个应用程序在后台开启数据库的操作,然后处理其他的工作(例如管理用户的接口)来等待后台操作的完成。因为 Java 编程语言提供了多线程的环境,因此提供异步

39、命令的执行似乎就没有必要了。如果想要异步地执行命令,程序开发人员能够很容易地创建一个隔离的线程。一些驱动也许允许更多的并发执行,但是开发人员应该能够设想出完全的并发执行场景。如果该驱动需要某种形式的同步,那么驱动应该要提供。在这种情形下,唯一的不同应该是应用程序并发运行的次数会降低。例如:在同一连接中的两个命令对象能够并发地执行,并且它们的结果集对象能够被并发地处理(从开发者的角度看)。一些驱动将完全提供这种并发能力。其他的也许执行一个命令并且在处理下个结果集之前一直等到第一个处理完成。为截断的输入参数抛出异常如果输入的参数被截断,那么 DataTruncation 的异常应该被抛出,参见“

40、Data Truncation ”,获取更多的信息。为 SQL99 数据类型使用默认的行为( JDBC 2.0 ) 差异性 由于在数据库功能和语法上的差异,在驱动的实现上 JDBC 允许一些差异。数据库所使用的 SQL 也许不同。例如:对于 Outer Joins ,不同的数据库提供了不同的支持。而且,许多 SQL 特性也许在不同的数据库间存在差异。 Java.sql.DatabaseMetaData接口提供了许多的方法,通过使用这些方法,用户能够确切地知道当前的数据库支持哪些 SQL 特性。对于驱动开发人员来说,必须确保 DatabaseMetaData 的方法能够返回准确的信息,即 DBM

41、S 支持哪些特性和不支持哪些特性。处理不支持的功能 当数据库不支持某种功能时,驱动需要作出相应的处理。例如:一些数据库不支持存储过程的 OUT 参数。在这种情形下, CallableStatement 方法中针对 OUT 参数的方法( registerOutParameter 和相应的 getter 方法)将不能应用,并且当用户调用时,要抛出 SQLException 。基本属性的差异 在一些基本的属性方面也允许有差异,例如:事务的隔离级别。当前数据库的默认属性和这些属性的范围可以通过 DatabaseMetaData 的方法获取。增加的功能 数据库厂商可能会增加额外的功能,这样就会创建 JD

42、BC 类的子类来提供这些额外的功能。例如: Foobah 公司支持了 SQL99 中的 NCHAR 和 NVCHAR 类型,该公司也许会定义一个新的 JAVA 类型 foobah.sql.FooBahType 来扩展 java.sql.Types 。驱动的安全性 使用 SQLException 作为异常 如果 DBMS 不支持某个功能,方法中要抛出 SQLException 。 有些情形下, Java RunTimeException 和 SQLException 也许会重叠。例如:如果一个方法希望一个参数是 java.sql.Types ,结果却提供了其他的类型,那么, IllegalArg

43、umentException或 SQLException。这样,推荐抛出SQLException,因为那将给予JDBC更多对Error的控制。实现的建议预检索行记录 提供“ Finalize ”方法 避免实现上的依赖 2.实现 Connection 和 Statement Pooling在数据库应用程序中获取数据源的连接是一个更加昂贵的操作。因此,为了重用物理连接,实现池化连接的机制能够在性能上提供利益。 JDBC API 提供了一个类( ConnectionEvent )和三个接口( ConnectionEventListener , ConnectionPoolDataSource 和 P

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

45、两个连接池。 类似地,重用PreparedStatement对象能够增强性能,尤其当prepared statement很大并且要被使用多次的时候。驱动和DBMS也许会花费很多的资源来预编译(原文:precompiling)Statement并且为了执行来准备一个策略,因此为Statement准备一次而不是多次是更加地有效。当创建Statements的连接被池化的时候,Statements也许会被池化。JDBC 3.0规范为ConnectionPoolDataSource增加了一些属性,这些属性能够创建Statement Pool的初始大小,和在池中被维护的Statement的最小数目,等等。

46、这些属性在实现中被设置,并且不是暴露给应用程序开发人员的API一部分。从应用程序开发人员的视角考虑,对于Statement Pooling没有新的API。实现连接池和 Statement Pooling 必须对用户完全透明。一个例外是驱动应该有关闭自己对连接池实现的能力,以便使用应用程序服务器的实现。应用程序能够透明地创建,使用和关闭连接,不管是否使用了连接池。同样地,应用程序每次创建新的 PreparedStatement 对象的方式也要透明。唯一的不同是如果程序员知道连接池有效,那么他 / 她也许会更好地使用 prepared statements 。但是,一般地,在性能地改善上应用程序会

47、开启使用连接池和 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测试的驱动功能。它们是免费地并且可以从以下网址下载: 如何安装和运行测试套件的文档在以下的网址:通过测试套件暗

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

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论