JDBC 驅(qū)動(dòng)開發(fā)準(zhǔn)則 (Driver GuideLines)

          JDBC 驅(qū)動(dòng)開發(fā)準(zhǔn)則( Driver Guidelines

          譯者序( Preface

          該準(zhǔn)則來源“ <<JDBC API Tutorial And Reference,Third Edition>> 中的附錄 A For Driver Writers ”。希望能夠?qū)Υ蠹矣兴鶐椭?,尤其是開發(fā)數(shù)據(jù)庫(kù)驅(qū)動(dòng)的,希望能有一個(gè)整體的開發(fā)概念,根據(jù)準(zhǔn)則中的描述,深入到每個(gè)開發(fā)要點(diǎn)和細(xì)節(jié),結(jié)合實(shí)際的 DBMS 作出正確的選擇。

          作者: Maydene Fisher,Jon Ellis,Jonathan Bruce??????????? ??? 譯者:湯泳( Miker.Tang

          由于時(shí)間的倉(cāng)促和翻譯的不到位,有許多地方值得推敲,請(qǐng)大家及時(shí)反饋 tangyong@fnst.com.cn ,謝謝!

          對(duì)所有驅(qū)動(dòng)的要求

          這部分為 JDBC 驅(qū)動(dòng)的標(biāo)準(zhǔn)實(shí)現(xiàn)提供了要求。一般地,不要求 JDBC 驅(qū)動(dòng)提供數(shù)據(jù)庫(kù)管理系統(tǒng)不支持的特性。

          準(zhǔn)則( Guidelines

          以下的準(zhǔn)則適用于 JDBC 1.0,JDBC 2.0 JDBC 3.0 API 的實(shí)現(xiàn)。

          ????????? JDBC API 需要支持 SQL92 標(biāo)準(zhǔn)指定的 SQL 命令。參見“ 支持 SQL92擴(kuò)展標(biāo)準(zhǔn) ”以獲取更多的細(xì)節(jié)。

          ????????? 驅(qū)動(dòng)必須支持 escape syntax 。“ 支持 SQL92 擴(kuò)展標(biāo)準(zhǔn) ”給予了 escape syntax 更多的細(xì)節(jié)。

          ????????? 驅(qū)動(dòng)必須支持事務(wù)。

          ????????? 驅(qū)動(dòng)應(yīng)該提供對(duì)潛在數(shù)據(jù)源實(shí)現(xiàn)的每個(gè)特性的訪問能力,包括 JDBC API 擴(kuò)展的特性。當(dāng)不能支持某個(gè)特性時(shí),相應(yīng)的方法要拋出 SQLException 。目的是對(duì)于使用 JDBC API 的應(yīng)用程序能夠訪問同樣的特性集。

          ????????? 如果一個(gè) DatabaseMetaData 的方法暗示了支持某個(gè)給定的特性,那么就像在相關(guān)的規(guī)范中描述的那樣,通過標(biāo)準(zhǔn)的語法和語義必須要支持。這也許需要驅(qū)動(dòng)提供到數(shù)據(jù)源原生 API 或不同于標(biāo)準(zhǔn)的 SQL 語義的映射。

          ????????? 如果支持某個(gè)特性,相關(guān)的 metadata 方法必須要實(shí)現(xiàn)。例如:如果 JDBC API 的實(shí)現(xiàn)支持 RowSet 接口,那么也要實(shí)現(xiàn) RowSetMetaData 接口。

          ????????? 如果不支持某個(gè)特性,相應(yīng)的 DatabaseMetaData 中的方法也必須要給出說明。試圖訪問不支持的特性將導(dǎo)致 SQLException 被拋出。

          ?

          在接口中實(shí)現(xiàn)方法

          ?????? JDBC 1.0 API 的接口中所有的方法必須要實(shí)現(xiàn)以便至少支持 ANSI SQL 92 X/Open SQL CLI JDBC 2.0 API JDBC 3.0 API 必須要實(shí)現(xiàn)來支持 ANSI SQL 92,ANSI SQL 99 相關(guān)的部分和 X/Open SQL CLI

          ?????? 除基本的標(biāo)準(zhǔn)以外,如果 DBMS 不支持某個(gè)特性,驅(qū)動(dòng)也不必支持。例如:如果 DBMS 不支持 SQL 99 中的數(shù)據(jù)類型,那么實(shí)現(xiàn)支持這些新的類型( Array,Blob,Clob,Ref,SQLData,SQLInput,SQLOutput Struct )的接口就是可選的?;蛘?,如果 DBMS 不支持某個(gè)可選包的特性,諸如 connection pooling ,那么支持 connection pooling Connection Event,ConnectionEventListener,ConnectionPoolDataSource,PooledConnection )的接口就是可選的。如果某個(gè)方法支持 DBMS 不包括的特性,那么該方法的實(shí)現(xiàn)將拋出 SQLException 。

          ?????? Metadata 接口應(yīng)該被完全實(shí)現(xiàn)。 DatabaseMetaData 接口的目的是告訴用戶 DBMS 支持哪些特性和不支持哪些特性,因此每個(gè)方法都要實(shí)現(xiàn)。同樣地, ResultSetMetaData ParameterMetaData 接口要完全被實(shí)現(xiàn)。提供 javax.sql.RowSet 實(shí)現(xiàn)的驅(qū)動(dòng)提供商也應(yīng)該提供一個(gè) javax.sql.RowSetMetaData 接口的完全實(shí)現(xiàn)。


          注意:
          JDBC 可選包中的接口已經(jīng)是 JDBC 3.0 API 的一部分,并且 JDBC 驅(qū)動(dòng)應(yīng)該實(shí)現(xiàn)來作為核心的 JDBC API 。但是, RowSet 接口和支持它的接口并不包含在里面,因?yàn)樗鼈兛梢詫?shí)現(xiàn)在 JDBC API 的上層,這樣就不作為驅(qū)動(dòng)實(shí)現(xiàn)的一部分了。 支持分布式事務(wù)的 JDBC 驅(qū)動(dòng)必須支持 XAConnection XADataSource 接口。

          ?

          兼容 JDBC 1.0 API 的要求

          為了兼容 JDBC 1.0 API ,驅(qū)動(dòng)實(shí)現(xiàn)需要做以下:

          ????????? 堅(jiān)持上面的準(zhǔn)則和要求。

          ????????? 完全實(shí)現(xiàn)下列接口:

          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 ,驅(qū)動(dòng)實(shí)現(xiàn)需要做以下:

          ????????? 符合 JDBC 1.0 API 的要求。

          ????????? 完全實(shí)現(xiàn) DatabaseMetaData 接口,包括在 JDBC 2.0 API 中增加的下列方法:

          deletesAreDetected

          getConnection

          getUDTs

          insertsAreDetected

          othersDeletesAreVisible

          othersInsertsAreVisible

          othersUpdatesAreVisible

          ownDeletesAreVisible

          ownInsertsAreVisible

          ownUpdatesAreVisible

          supportsBatchUpdates

          supportsResultSetConcurrency

          supportsResultSetType

          updatesAreDetected

          ?

          ????????? 實(shí)現(xiàn)下面 ResultSetMetaData 中其他的方法:

          getColumnClassName

          getColumnType

          getColumnTypeName

          兼容 JDBC 3.0 API 的要求

          為了兼容 JDBC 3.0 API ,驅(qū)動(dòng)實(shí)現(xiàn)需要做以下:

          ????????? 符合 JDBC 2.0 API 的要求

          ????????? 包括以下所需的接口:

          java.sql.ParameterMetaData

          java.sql.Savepoint

          ?

          ????????? 完全實(shí)現(xiàn) DatabaseMetaData 接口,包括在 JDBC 3.0 API 中增加的下列方法:

          supportsSavepoints

          supportsNamedParameters

          supportsMultipleOpenResults

          supportsGetGeneratedKeys

          getSuperTypes

          getSuperTables

          getAttributes

          getResultSetHoldability

          supportsResultSetHoldability

          getSQLStateType

          getDatabaseMajorVersion

          getDatabaseMinorVersion

          getJDBCmajorVersion

          getJDBCMinorVersion

          已經(jīng)被實(shí)現(xiàn)的 API

          下面的類和異常在 JDBC 3.0 API 中已經(jīng)完全被實(shí)現(xiàn)了:

          ·???????? 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 驅(qū)動(dòng)也必須符合下面列舉的要求:

          實(shí)現(xiàn) Static Initializer

          每個(gè) Driver 類應(yīng)該包含一個(gè)特殊的靜態(tài)區(qū)域,有時(shí)被稱作 Static Initializer ,當(dāng)使用 DriverManager 來加載 Driver 類時(shí), Driver 類的 Static Initializer 被調(diào)用。當(dāng)加載 Driver 類時(shí), Static Initializer 完成以下兩件事:

          1.? 創(chuàng)建 Driver 類的實(shí)例。

          2.? 通過調(diào)用 DriverManager.registerDriver 注冊(cè)新創(chuàng)建的 Driver 實(shí)例。

          下面的代碼演示了 Static Initializer

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

          ?

          ?

          ?

          ?

          ?

          ?

          ?

          ?

          ?


          ?

          當(dāng)完成以上兩件事之后,用戶通過調(diào)用 Class.forName Driver 類名作為參數(shù))方法能夠加載和注冊(cè) JDBC 驅(qū)動(dòng)。


          ?注意:Static Initializer
          僅僅適用使用 DriverManager 加載驅(qū)動(dòng)的方式。通過 DataSource API 加載驅(qū)動(dòng)不會(huì)使用 DriverManager 自動(dòng)地注冊(cè),而且在實(shí)現(xiàn)上也不應(yīng)該包含 Static Initializer DriverManager DriverPropertyInfo 類包括 Driver 接口也許在將來會(huì)被削弱。

          ?

          支持 SQL92 擴(kuò)展標(biāo)準(zhǔn)

          ?

          ?

          支持 Scalar 函數(shù)

          支持 Scalar 函數(shù)需要一些額外的解釋。 JDBC 支持?jǐn)?shù)字型,字符串型,時(shí)間型,日期型, System 和轉(zhuǎn)換成 Scalar 值的函數(shù)。對(duì)于那些想要比“ Statements 中的 SQL Escape Syntax ”更多信息的人來說, X/Open Group CLI 規(guī)范提供了關(guān)于 Scalar 函數(shù)語義更多的信息。以下是這些函數(shù)的列表。

          如果 DBMS 支持 Scalar 函數(shù),驅(qū)動(dòng)也應(yīng)該支持。因?yàn)椴煌?/span> DBMS 對(duì) Scalar 函數(shù)語法上的支持會(huì)有不同,所以驅(qū)動(dòng)就是或者將 Scalar 函數(shù)映射成合適的語法,或者是在驅(qū)動(dòng)中直接實(shí)現(xiàn)這些函數(shù)。

          用戶通過調(diào)用 metadata 中的方法應(yīng)該能發(fā)現(xiàn)哪些函數(shù)被支持。例如:方法 DatabaseMetaData.getNumericFunctions 應(yīng)該返回一個(gè)逗號(hào)分隔的被 Open Group CLI 支持的 numeric 函數(shù)列表。類似地,方法 DatabaseMetaData.getStringFunctions 應(yīng)該返回一個(gè) string 函數(shù)列表,等等。

          以下是按照種別列出的 Scalar 函數(shù):

          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 結(jié)果集游標(biāo)提供了不同的方法,因此,在結(jié)果集中很容易更新或刪除一個(gè)特別的行。但是, JDBC 1.0 API 僅僅提供了簡(jiǎn)單的游標(biāo)支持,這也就使得 positioned Update Delete 有點(diǎn)復(fù)雜。

          ?

          ?????? 當(dāng)使用 executeQuery 執(zhí)行查詢的時(shí)候,返回結(jié)果集且游標(biāo)位于第一行記錄的前面。直到結(jié)果集對(duì)象或創(chuàng)建該結(jié)果集的 Statement 關(guān)閉為止,游標(biāo)將保持有效。如果驅(qū)動(dòng)不支持游標(biāo)的 position 方法,那么應(yīng)用程序必須通過調(diào)用 ResultSet.getCursorName 方法來獲取游標(biāo)的名稱。這個(gè)游標(biāo)的名稱能夠被使用在 position Update Delete 語句中。


          注意:
          所有
          DBMS 都支持 position Update Delete 。應(yīng)用程序能夠使用 DatabaseMetaData.supportsPositionedUpdate DatabaseMetaData.supportsPostionedDelete 方法來決定當(dāng)前的連接是否支持。因?yàn)樵S多 DBMS Select 語句( in Select For Update )中都不支持“ for update ”,所以驅(qū)動(dòng)必須要檢查并且實(shí)現(xiàn)這個(gè)語義。這個(gè)語法( for update )的目的是通知生成的結(jié)果集將使用 position Update Delete 。 另外, JDBC 3.0 API 允許應(yīng)用程序指定結(jié)果集對(duì)象的持久性( Holdability ),這就允許在事務(wù)過程中創(chuàng)建的結(jié)果集對(duì)象在事務(wù)被提交的生命周期以外被維護(hù)。這也意味著 JDBC 驅(qū)動(dòng)必須考慮額外的鎖定功能。

          ?????? 當(dāng)支持 position update delete 時(shí), DBMS/Driver 必須確保被篩選的行能夠被鎖定以便 postion update 不會(huì)導(dǎo)致更新異常或是其他的并發(fā)問題。

          ?

          ?

          支持多線程

          java.sql javax.sql 中對(duì)象的所有操作都需要多線程的安全。它們必須能正確地處理幾個(gè)線程同時(shí)調(diào)用同一個(gè)對(duì)象。換句話說,在一個(gè)線程中執(zhí)行的命令不應(yīng)該阻塞在另一個(gè)線程中的執(zhí)行。特別地,當(dāng)使用多線程時(shí), JDBC 驅(qū)動(dòng)應(yīng)該能正確地操作。

          一個(gè)具體使用多線程的例子是一個(gè)長(zhǎng)時(shí)間運(yùn)行的命令能夠被取消。通過使用一個(gè)線程執(zhí)行該命令而另一個(gè)線程能夠取消掉來達(dá)到目的。

          盡管在實(shí)際中能夠預(yù)想決大多數(shù) JDBC 對(duì)象將以單線程的方式被訪問,但是也需要支持多線程的方式。

          一些數(shù)據(jù)庫(kù)的 API ,如 ODBC ,提供了異步執(zhí)行 SQL 語句的機(jī)制。這就允許一個(gè)應(yīng)用程序在后臺(tái)開啟數(shù)據(jù)庫(kù)的操作,然后處理其他的工作(例如管理用戶的接口)來等待后臺(tái)操作的完成。

          因?yàn)?/span> Java 編程語言提供了多線程的環(huán)境,因此提供異步命令的執(zhí)行似乎就沒有必要了。如果想要異步地執(zhí)行命令,程序開發(fā)人員能夠很容易地創(chuàng)建一個(gè)隔離的線程。

          一些驅(qū)動(dòng)也許允許更多的并發(fā)執(zhí)行,但是開發(fā)人員應(yīng)該能夠設(shè)想出完全的并發(fā)執(zhí)行場(chǎng)景。如果該驅(qū)動(dòng)需要某種形式的同步,那么驅(qū)動(dòng)應(yīng)該要提供。在這種情形下,唯一的不同應(yīng)該是應(yīng)用程序并發(fā)運(yùn)行的次數(shù)會(huì)降低。

          例如:在同一連接中的兩個(gè)命令對(duì)象能夠并發(fā)地執(zhí)行,并且它們的結(jié)果集對(duì)象能夠被并發(fā)地處理(從開發(fā)者的角度看)。一些驅(qū)動(dòng)將完全提供這種并發(fā)能力。其他的也許執(zhí)行一個(gè)命令并且在處理下個(gè)結(jié)果集之前一直等到第一個(gè)處理完成。

          為截?cái)嗟妮斎雲(yún)?shù)拋出異常

          如果輸入的參數(shù)被截?cái)啵敲?/span> DataTruncation 的異常應(yīng)該被拋出,參見“ Data Truncation ”,獲取更多的信息。

          SQL99 數(shù)據(jù)類型使用默認(rèn)的行為( JDBC 2.0

          ?

          差異性

          ?????? 由于在數(shù)據(jù)庫(kù)功能和語法上的差異,在驅(qū)動(dòng)的實(shí)現(xiàn)上 JDBC 允許一些差異。數(shù)據(jù)庫(kù)所使用的 SQL 也許不同。例如:對(duì)于 Outer Joins ,不同的數(shù)據(jù)庫(kù)提供了不同的支持。而且,許多 SQL 特性也許在不同的數(shù)據(jù)庫(kù)間存在差異。

          ?????? Java.sql..DatabaseMetaData 接口提供了許多的方法,通過使用這些方法,用戶能夠確切地知道當(dāng)前的數(shù)據(jù)庫(kù)支持哪些 SQL 特性。對(duì)于驅(qū)動(dòng)開發(fā)人員來說,必須確保 DatabaseMetaData 的方法能夠返回準(zhǔn)確的信息,即 DBMS 支持哪些特性和不支持哪些特性。

          處理不支持的功能

          ?????? 當(dāng)數(shù)據(jù)庫(kù)不支持某種功能時(shí),驅(qū)動(dòng)需要作出相應(yīng)的處理。例如:一些數(shù)據(jù)庫(kù)不支持存儲(chǔ)過程的 OUT 參數(shù)。在這種情形下, CallableStatement 方法中針對(duì) OUT 參數(shù)的方法( registerOutParameter 和相應(yīng)的 getter 方法)將不能應(yīng)用,并且當(dāng)用戶調(diào)用時(shí),要拋出 SQLException 。

          基本屬性的差異

          ?????? 在一些基本的屬性方面也允許有差異,例如:事務(wù)的隔離級(jí)別。當(dāng)前數(shù)據(jù)庫(kù)的默認(rèn)屬性和這些屬性的范圍可以通過 DatabaseMetaData 的方法獲取。

          增加的功能

          ?????? 數(shù)據(jù)庫(kù)廠商可能會(huì)增加額外的功能,這樣就會(huì)創(chuàng)建 JDBC 類的子類來提供這些額外的功能。例如: Foobah 公司支持了 SQL99 中的 NCHAR NVCHAR 類型,該公司也許會(huì)定義一個(gè)新的 JAVA 類型 foobah.sql.FooBahType 來擴(kuò)展 java.sql.Types 。

          驅(qū)動(dòng)的安全性

          ??????

          使用 SQLException 作為異常

          ?????? 如果 DBMS 不支持某個(gè)功能,方法中要拋出 SQLException 。

          ?????? 有些情形下, Java RunTimeException SQLException 也許會(huì)重疊。例如:如果一個(gè)方法希望一個(gè)參數(shù)是 java.sql.Types ,結(jié)果卻提供了其他的類型,那么, IllegalArgumentException SQLException。這樣,推薦拋出SQLException,因?yàn)槟菍⒔o予JDBC更多對(duì)Error的控制。

          實(shí)現(xiàn)的建議

          預(yù)檢索行記錄

          ?

          提供“ Finalize ”方法

          ?

          避免實(shí)現(xiàn)上的依賴

          ?

          2.

          實(shí)現(xiàn) Connection Statement Pooling

          在數(shù)據(jù)庫(kù)應(yīng)用程序中獲取數(shù)據(jù)源的連接是一個(gè)更加昂貴的操作。因此,為了重用物理連接,實(shí)現(xiàn)池化連接的機(jī)制能夠在性能上提供利益。 JDBC API 提供了一個(gè)類( ConnectionEvent )和三個(gè)接口( ConnectionEventListener ConnectionPoolDataSource PooledConnection )來作為連接池的實(shí)現(xiàn)策略。

          ?????? 這些 API 決定了連接池如果工作的一般的準(zhǔn)則,但是并沒有提出連接池如何實(shí)現(xiàn)的具體細(xì)節(jié)。而且, JDBC 3.0 規(guī)范并沒有定義在何處實(shí)現(xiàn),留出了很大的實(shí)現(xiàn)自由。典型地,一個(gè)應(yīng)用程序服務(wù)器將實(shí)現(xiàn)連接池和分布式事務(wù)的管理。驅(qū)動(dòng)提供商會(huì)實(shí)現(xiàn) DataSource ConnectionPoolDataSource 接口以便它們能和實(shí)現(xiàn)連接池的 J2EE 應(yīng)用程序服務(wù)器協(xié)同工作。如果一個(gè) JDBC 驅(qū)動(dòng)包含了對(duì)連接池管理的實(shí)現(xiàn),那么它應(yīng)該提供一種方式,使得能夠關(guān)閉驅(qū)動(dòng)的實(shí)現(xiàn)。這樣,應(yīng)用程序能夠選擇使用應(yīng)用程序服務(wù)器的實(shí)現(xiàn),這樣可以防止建立兩個(gè)連接池。

          ????????類似地,重用PreparedStatement對(duì)象能夠增強(qiáng)性能,尤其當(dāng)prepared statement很大并且要被使用多次的時(shí)候。驅(qū)動(dòng)和DBMS也許會(huì)花費(fèi)很多的資源來預(yù)編譯(原文:precompilingStatement并且為了執(zhí)行來準(zhǔn)備一個(gè)策略,因此為Statement準(zhǔn)備一次而不是多次是更加地有效。當(dāng)創(chuàng)建Statements的連接被池化的時(shí)候,Statements也許會(huì)被池化。JDBC 3.0規(guī)范為ConnectionPoolDataSource增加了一些屬性,這些屬性能夠創(chuàng)建Statement Pool的初始大小,和在池中被維護(hù)的Statement的最小數(shù)目,等等。這些屬性在實(shí)現(xiàn)中被設(shè)置,并且不是暴露給應(yīng)用程序開發(fā)人員的API一部分。從應(yīng)用程序開發(fā)人員的視角考慮,對(duì)于Statement Pooling沒有新的API。

          實(shí)現(xiàn)連接池和 Statement Pooling 必須對(duì)用戶完全透明。一個(gè)例外是驅(qū)動(dòng)應(yīng)該有關(guān)閉自己對(duì)連接池實(shí)現(xiàn)的能力,以便使用應(yīng)用程序服務(wù)器的實(shí)現(xiàn)。應(yīng)用程序能夠透明地創(chuàng)建,使用和關(guān)閉連接,不管是否使用了連接池。同樣地,應(yīng)用程序每次創(chuàng)建新的 PreparedStatement 對(duì)象的方式也要透明。唯一的不同是如果程序員知道連接池有效,那么他 / 她也許會(huì)更好地使用 prepared statements 。但是,一般地,在性能地改善上應(yīng)用程序會(huì)開啟使用連接池和 Statement Pooling 。

          JDBC 測(cè)試套件

          ??? 驅(qū)動(dòng)提供商通過使用JDBC測(cè)試套件能夠測(cè)試它們的驅(qū)動(dòng)是否和J2EE平臺(tái)兼容。有兩個(gè)版本:

          ·???????? 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

          這些測(cè)試套件覆蓋了經(jīng)過兼容J2EE測(cè)試的驅(qū)動(dòng)功能。它們是免費(fèi)地并且可以從以下網(wǎng)址下載:

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

          ??? 如何安裝和運(yùn)行測(cè)試套件的文檔在以下的網(wǎng)址:

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

          通過測(cè)試套件暗示了一個(gè)驅(qū)動(dòng)是兼容其他符合J2EE規(guī)范的產(chǎn)品,但是并不意味這個(gè)驅(qū)動(dòng)能夠被標(biāo)記兼容J2EE。驅(qū)動(dòng)必須要通過一個(gè)外部的測(cè)試組織來測(cè)試是兼容的。完全的驅(qū)動(dòng)認(rèn)證過程的說明在如下的網(wǎng)址:

          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 平臺(tái)上開發(fā)應(yīng)用程序?qū)缀蹩傁胧褂?/span> JDBC API 起訪問一個(gè)或更多 DBMS 。因此,對(duì)于驅(qū)動(dòng)提供商來說,能夠很容易地將 JDBC 驅(qū)動(dòng)連接到 J2EE 應(yīng)用程序服務(wù)器是件很有趣的事。

          J2EE 連接器的架構(gòu)

          ?????? J2EE 連接器架構(gòu) 1.0 規(guī)范和 1.5 規(guī)范提供了一個(gè)框架,能夠以一種可插拔( pluggable )的方式連接 J2EE 應(yīng)用程序服務(wù)器到額外的資源,例如: DBMS 。完成這一功能的軟件被稱作資源適配器( Resource Adapter ),或者叫 Connector

          ?????? 連接器架構(gòu)的核心是一組契約( Contracts )。滿足這些契約的驅(qū)動(dòng)實(shí)現(xiàn)將能夠插入到任何滿足這些契約的 J2EE 應(yīng)用程序服務(wù)器中。服務(wù)提供接口( SPI )契約定義了 J2EE 服務(wù)器和資源適配器必須實(shí)現(xiàn)的內(nèi)容,以下是需要實(shí)現(xiàn)的領(lǐng)域:

          ????????? 事務(wù)管理( Transaction management

          ????????? 連接池管理( Connection pool management

          ????????? 安全性( Security

          以下的接口描述了和上述契約等價(jià)的服務(wù):

          ????????? 數(shù)據(jù)源(DataSource)

          ????????? 池化的數(shù)據(jù)源(ConnectionPoolDataSource)

          ????????? 支持分布式事務(wù)的數(shù)據(jù)源(XADataSource)

          DataSource ConnectionPoolDataSource 接口描述了涉及連接池相關(guān)的服務(wù)。 XADataSource 接口描述涉及分布式事務(wù)相關(guān)的服務(wù)。 JDBC 并沒有提供與安全性契約相關(guān)的 API ,因?yàn)檎J(rèn)證總是要包含用戶名和密碼。

          ?????? 為了使用連接器系統(tǒng)提供的的契約,驅(qū)動(dòng)提供商有不同的選擇:

          ????????? 寫一系列的類,用來包裝( Wrap JDBC 驅(qū)動(dòng)并且實(shí)現(xiàn)連接器的契約。構(gòu)建這些包裝器相當(dāng)?shù)刂苯樱⑶覒?yīng)該允許提供商足夠快地提供資源適配器,以便當(dāng)應(yīng)用程序服務(wù)器提供商已經(jīng)實(shí)現(xiàn)了連接器契約時(shí)能夠有用。

          ????????? 直接實(shí)現(xiàn)連接器契約。這樣將避免包裝帶來的負(fù)擔(dān),但是實(shí)現(xiàn)將會(huì)更加地耗時(shí)和耗力。但是,這是一個(gè)長(zhǎng)期的選擇。

          ????????? 使用 JDBC 連接器實(shí)現(xiàn)。相關(guān)的信息可以從以下網(wǎng)址下載:

          ?

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

          ??????

          ?????? JDBC 3.0 規(guī)范,章節(jié) 19.3 給出了以連接器資源包( RAR )文件格式包裹 JDBC 驅(qū)動(dòng)的細(xì)節(jié)。下載相關(guān)的文檔和 RAR 文件解釋了 JDBC 連接器如何地工作并且如何地部署它。廠商將會(huì)發(fā)現(xiàn)使用 SPI RAR 文件非常地容易因?yàn)樗鼈儾槐卦隍?qū)動(dòng)實(shí)現(xiàn)中改變?nèi)魏蔚拇a。

          ??? 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 會(huì)飛的魚 閱讀(1161) 評(píng)論(1)  編輯  收藏 所屬分類: JDBC 驅(qū)動(dòng)開發(fā)

          評(píng)論

          # re: JDBC 驅(qū)動(dòng)開發(fā)準(zhǔn)則 (Driver GuideLines) 2007-01-08 16:02 你最親愛的老婆

          我是不是也該弄篇論文在我的BLOG上啊,這樣似乎會(huì)顯得比較有深度啊...  回復(fù)  更多評(píng)論   


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          <2025年7月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(2)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          相冊(cè)

          友情鏈接

          開源鏈接

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 若羌县| 安徽省| 四平市| 哈密市| 都兰县| 清丰县| 琼中| 平泉县| 饶平县| 武功县| 古丈县| 眉山市| 永登县| 滦南县| 顺义区| 克什克腾旗| 大厂| 乌兰察布市| 龙海市| 全椒县| 宜兰县| 盐边县| 临沂市| 屏边| 湛江市| 平泉县| 宿州市| 堆龙德庆县| 志丹县| 龙泉市| 潼南县| 巴林左旗| 陆河县| 塔城市| 邯郸市| 阜新市| 瑞昌市| 巢湖市| 诸暨市| 四平市| 苏尼特左旗|