1、JDBC3.0規(guī)范中數(shù)據(jù)庫連接池框架
JDBC3.0規(guī)范中通過提供了一個(gè)支持?jǐn)?shù)據(jù)庫連接池的框架,這個(gè)框架僅僅規(guī)定了如何支持連接池的實(shí)現(xiàn),而連接池的具體實(shí)現(xiàn)JDBC 3.0規(guī)范并沒有做相關(guān)的規(guī)定。通過這個(gè)框架可以讓不同角色的開發(fā)人員共同實(shí)現(xiàn)數(shù)據(jù)庫連接池。
通過JDBC3.0規(guī)范可以知道具體數(shù)據(jù)庫連接池的實(shí)現(xiàn)可以分為JDBC Driver級(jí)和Application Server級(jí)。在JDBC Driver級(jí)的實(shí)現(xiàn)中任何相關(guān)的工作均由特定數(shù)據(jù)庫廠商的JDBC Drvier的開發(fā)人員來具體實(shí)現(xiàn),即JDBC Driver既需要提供對(duì)數(shù)據(jù)庫連接池的支持同時(shí)也必須對(duì)數(shù)據(jù)庫連接池進(jìn)行具體實(shí)現(xiàn)。而在Application Server級(jí)中數(shù)據(jù)庫連接池的實(shí)現(xiàn)中特定數(shù)據(jù)庫廠商的JDBC Driver開發(fā)人員和Application Server開發(fā)人員來共同實(shí)現(xiàn)數(shù)據(jù)庫連接池的實(shí)現(xiàn)(但是現(xiàn)在大多數(shù)Application Server廠商實(shí)現(xiàn)的連接池的機(jī)制和規(guī)范中提到有差異),其中特定數(shù)據(jù)庫廠商的JDBC Driver提供數(shù)據(jù)庫連接池的支持而特定的Application Server廠商提供數(shù)據(jù)庫連接池的具體實(shí)現(xiàn)。
JDBC3.0規(guī)范規(guī)定了如下的類和接口來支持?jǐn)?shù)據(jù)庫連接池的實(shí)現(xiàn)。
javax.sql.ConnectionEvent
javax.sql.ConnectionPoolDataSource
javax.sql.PooledConnection
javax.sql.ConnectionEventListener |
其中除javax.sql.ConnectionEvent是類,其它的均為接口。
圖1 JDBC3.0連接池框架的關(guān)系圖
通過此圖可以大概的了解相關(guān)接口在一個(gè)典型的三層環(huán)境中應(yīng)用程序的位置。
2、檢索自動(dòng)產(chǎn)生的關(guān)鍵字
為了解決對(duì)獲取自動(dòng)產(chǎn)生的或自動(dòng)增加的關(guān)鍵字的值的需求,JDBC 3.0 API 現(xiàn)在將獲取這種值變得很輕松。要確定任何所產(chǎn)生的關(guān)鍵字的值,只要簡(jiǎn)單地在語句的 execute() 方法中指定一個(gè)可選的標(biāo)記,表示您有興趣獲取產(chǎn)生的值。您感興趣的程度可以是 Statement.RETURN_GENERATED_KEYS,也可以是 Statement.NO_GENERATED_KEYS。在執(zhí)行這條語句后,所產(chǎn)生的關(guān)鍵字的值就會(huì)通過從 Statement 的實(shí)例方法 getGeneratedKeys() 來檢索 ResultSet 而獲得,ResultSet 包含了每個(gè)所產(chǎn)生的關(guān)鍵字的列,下面的示例創(chuàng)建一個(gè)新的作者并返回對(duì)應(yīng)的自動(dòng)產(chǎn)生的關(guān)鍵字。
……
Statement stmt = conn.createStatement();
// Obtain the generated key that results from the query.
stmt.executeUpdate("INSERT INTO authors " +
"(first_name, last_name) " +
"VALUES (‘Ghq’, ‘Wxl’)",
Statement.RETURN_GENERATED_KEYS);
ResultSet rs = stmt.getGeneratedKeys();
if ( rs.next() ) {
// Retrieve the auto generated key(s).
int key = rs.getInt();
}
…… |
3、返回多重結(jié)果
JDBC 2 規(guī)范的一個(gè)局限是,在任意時(shí)刻,返回多重結(jié)果的語句只能打開一個(gè) ResultSet。作為 JDBC 3.0 規(guī)范中改變的一個(gè)部分,規(guī)范將允許 Statement 接口支持多重打開的 ResultSets。然而,重要的是 execute() 方法仍然會(huì)關(guān)閉任何以前 execute() 調(diào)用中打開的 ResultSet。所以,要支持多重打開的結(jié)果,Statement 接口就要加上一個(gè)重載的 getMoreResults() 方法。新式的方法會(huì)做一個(gè)整數(shù)標(biāo)記,在 getResultSet() 方法被調(diào)用時(shí)指定前一次打開的 ResultSet 的行為。接口將按如下所示定義標(biāo)記:
CLOSE_ALL_RESULTS:當(dāng)調(diào)用 getMoreResults() 時(shí),所有以前打開的 ResultSet 對(duì)象都將被關(guān)閉。
CLOSE_CURRENT_RESULT:當(dāng)調(diào)用 getMoreResults() 時(shí),當(dāng)前的 ResultSet 對(duì)象將被關(guān)閉。
KEEP_CURRENT_RESULT:當(dāng)調(diào)用 getMoreResults() 時(shí),當(dāng)前的 ResultSet 對(duì)象將不會(huì)被關(guān)閉。
下面展示的是一個(gè)處理多重打開結(jié)果的示例。
……
String procCall;
// Set the value of procCall to call a stored procedure.
// …
CallableStatement cstmt = connection.prepareCall(procCall);
int retval = cstmt.execute();
if (retval == false) {
// The statement returned an update count, so handle it.
// …
} else { // ResultSet
ResultSet rs1 = cstmt.getResultSet();
// …
retval = cstmt.getMoreResults(Statement.KEEP_CURRENT_RESULT);
if (retval == true) {
ResultSet rs2 = cstmt.getResultSet();
// Both ResultSets are open and ready for use.
rs2.next();
rs1.next();
// …
}
}
…… |
4、在事務(wù)中使用 Savepoint
也許在 JDBC 3.0 中最令人興奮的附加特點(diǎn)就是 Savepoint 了。JDBC 2 中的事務(wù)支持讓開發(fā)人員可以控制對(duì)數(shù)據(jù)的并發(fā)訪問,從而保證持續(xù)數(shù)據(jù)總是保持一致的狀態(tài)。可惜的是,有時(shí)候需要的是對(duì)事務(wù)多一點(diǎn)的控制,而不是在當(dāng)前的事務(wù)中簡(jiǎn)單地對(duì)每一個(gè)改變進(jìn)行回滾。在JDBC 3.0 下,可以通過 Savepoint 獲得這種控制。Savepoint 接口允許您將事務(wù)分割為各個(gè)邏輯斷點(diǎn),以控制有多少事務(wù)需要回滾。下圖3 將說明如何在事務(wù)中運(yùn)用 Savepoint。
圖2 Savepoint 的直觀表示
你或許不是經(jīng)常需要使用 Savepoint。然而,在一種普遍的情況下 Savepoint 會(huì)發(fā)揮作用,那就是您需要作一系列的改變,但是在知道所有的結(jié)果之前不能確定應(yīng)該保留這些改變的哪一部分。下面的代碼示例說明了如何使用 Savepoint 接口。
......
conn.setAutoCommit(false);
// Set a conservative transaction isolation level.
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
Statement stmt = conn.createStatement();
int rows = stmt.executeUpdate( "INSERT INTO authors " +
" (first_name, last_name) VALUES " +
" ('Ghq', 'Wxl')");
// Set a named savepoint.
Savepoint svpt = conn.setSavepoint("NewAuthor");
// …
rows = stmt.executeUpdate( "UPDATE authors set type = 'fiction' " +
"WHERE last_name = 'Wxl'");
// …
conn.rollback(svpt);
// …
// The author has been added, but not updated.
conn.commit();
...... |
5、其他的特性
1)元數(shù)據(jù) API
元數(shù)據(jù) API 已經(jīng)得到更新,DatabaseMetaData 接口現(xiàn)在可以檢索 SQL 類型的層次結(jié)構(gòu),一種新的 ParameterMetaData 接口可以描述 PreparedStatement 對(duì)象中參數(shù)的類型和屬性。
2)CallableStatements 中已命名的參數(shù)
在 JDBC 3.0 之前,設(shè)置一個(gè)存儲(chǔ)過程中的一個(gè)參數(shù)要指定它的索引值,而不是它的名稱。 CallableStatement 接口已經(jīng)被更新了,現(xiàn)在您可以用名稱來指定參數(shù)。
3)數(shù)據(jù)類型的改變
JDBC 所支持的數(shù)據(jù)類型作了幾個(gè)改變,其中之一是增加了兩種新的數(shù)據(jù)類型。
為了便于修改 CLOB(Character Large OBject,字符型巨對(duì)象)、BLOB(Binary Large OBject,二進(jìn)制巨對(duì)象)和 REF(SQL 結(jié)構(gòu))類型的值,同名的數(shù)據(jù)類型接口都被更新了。接下來的是,因?yàn)槲覀儸F(xiàn)在能夠更新這些數(shù)據(jù)類型的值,所以 ResultSet 接口也被修改了,以支持對(duì)這些數(shù)據(jù)類型的列的更新,也包括對(duì) ARRAY 類型的更新。增加的兩種新的數(shù)據(jù)類型是 java.sql.Types.DATALINK 和 java.sql.Types.BOOLEAN。新增的數(shù)據(jù)類型指的是同名的 SQL 類型。DATALINK 提供對(duì)外部資源的訪問或 URL,而 BOOLEAN 類型在邏輯上和 BIT 類型是等同的,只是增加了在語義上的含義。DATALINK 列值是通過使用新的 getURL() 方法從 ResultSet 的一個(gè)實(shí)例中檢索到的,而 BOOLEAN 類型是通過使用 getBoolean() 來檢索的。
|