| PostgreSQL 7.4 文檔 | ||||
|---|---|---|---|---|
| Prev | Fast Backward | Chapter 31. JDBC 接口 | Fast Forward | Next |
JDBC 2 以一個附加的 API 的方式引入了標準連接池的特性,這個 附加的 API 叫做 JDBC 2.0 可選包(也稱作 JDBC 2.0 標準擴展)。因此這些特性就被包含到核心的 JDBC 3 API 中了。 如果用 JDK 1.3.x 和 JDBC 2.0 可選包 一起編譯 JDBC 驅動,那麼 PostgreSQL JDBC 驅動 就支持這些特性,或者是用 JDK 1.4 或更高的版本 (JDBC 3)一起,也支持這個特性。大多數應用服務器包含 JDBC 2.0 可選包,但我們也可以從 SUN 單獨獲得這些東西: JDBC下載站。
JDBC API 為連接池提供了一個客戶端和一個服務器端的接口。 客戶端接口是 javax.sql.DataSource, 通常就是應用代碼用來請求一個緩衝了的數據庫連接的東西。 服務器接口是 javax.sql.ConnectionPoolDataSource, 通常是大多數應用服務器和 PostgreSQL JDBC 驅動打交道的接口。
在應用服務器環境裡,應用服務器配置通常將指向 PostgreSQL ConnectionPoolDataSource 實現, 而應用組件代碼將通常要求一個由應用服務器實現的 DataSource(不是由 PostgreSQL)。
在一個沒有應用服務器的環境裡,PostgreSQL 提供了兩種應用可以直接使用的 DataSource 的實現。 一種實現執行連接池,另外一種只是簡單的通過 DataSource 接口提供訪問數據庫的連接, 而不使用任何緩衝池。同樣,這些實現不應該在一個應用服務器環境裡使用, 除非應用服務器不支持 ConnectionPoolDataSource 接口。
PostgreSQL 包含了一個用于 JDBC 2 的 ConnectionPoolDataSource 的實現,以及一個用于 JDBC 3 的實現:如 Table 31-1 所示。
Table 31-1. ConnectionPoolDataSource實現
| JDBC | 實現類 |
|---|---|
| 2 | org.postgresql.jdbc2.optional.ConnectionPool |
| 3 | org.postgresql.jdbc3.Jdbc3ConnectionPool |
兩種實現都使用了同樣的配置模式。JDBC 要求一個 ConnectionPoolDataSource 通過 JavaBean 屬性來實現, 在 Table 31-2 裡顯示, 因此每個這樣的屬性都存在獲取和設置方法:
Table 31-2. ConnectionPoolDataSource 配置屬性
| 屬性 | 類型 | 描述 |
|---|---|---|
| serverName | String | PostgreSQL 數據庫服務器主機名 |
| databaseName | String | PostgreSQL 數據庫名 |
| portNumber | int | PostgreSQL 數據庫服務器監聽的 TCP/IP 端口 (為 0 則使用缺省端口) |
| user | String | 用來進行數據庫連接的用戶 |
| password | String | 用來進行數據庫連接的口令 |
| defaultAutoCommit | boolean | 提交給調用者的時候連接是應該打開 autoCommit 還是應該關閉。 缺省是 false,關閉 autoCommit。 |
許多應用服務器使用屬性風格的語法來配置這些屬性, 因此把屬性當作一塊文本輸入應該並不罕見。 如果應用服務器提供了單塊的區域輸入所有屬性, 那麼它們應該像下面這樣列出:
serverName=localhost databaseName=test user=testuser password=testpassword
或者,如果使用分號而不是換行做分隔符,那麼看起來像:
serverName=localhost;databaseName=test;user=testuser;password=testpassword
PostgreSQL 包含兩個用于 JDBC 2 的 DataSource,還有兩個用于 JDBC 3的, 如 Table 31-3 所示。 連接池的實現在客戶端調用 close 方法的時候實際上並不關閉連接, 而是把連接返回到一個可用連接的連接池中給其它客戶端使用。 這樣就避免了任何重復打開和關閉連接造成的開銷,並且允許大量的客戶端分享相對較少的數據庫連接。
這裡提供的連接池數據源實現並非世上特性最豐富的。 比如,連接在池本身關閉之前絕對不會關閉;而且也沒有辦法縮小連接池。 同樣,非缺省配置的用戶的連接請求無法如池。許多應用服務器提供更加高級的連接池特性,並且使用的是 ConnectionPoolDataSource 實現。
Table 31-3. DataSource 實現
| JDBC | 連接池 | 實現類 |
|---|---|---|
| 2 | 否 | org.postgresql.jdbc2.optional.SimpleDataSource |
| 2 | 是 | org.postgresql.jdbc2.optional.PoolingDataSource |
| 3 | 否 | org.postgresql.jdbc3.Jdbc3SimpleDataSource |
| 3 | 是 | org.postgresql.jdbc3.Jdbc3PoolingDataSource |
所有實現使用同樣的配置模式。JDBC 要求 DataSource 通過 JavaBean 屬性配置, 在 Table 31-4 裡列出。 因此每種這個屬性都有獲取和設置屬性的方法。
Table 31-4. DataSource 配置屬性
| 屬性 | 類型 | 描述 |
|---|---|---|
| serverName | String | PostgreSQL 數據庫服務器主機名 |
| databaseName | String | PostgreSQL 數據庫名 |
| portNumber | int | PostgreSQL 數據庫服務器監聽的 TCP 端口 (或者 0 表示使用缺省端口) |
| user | String | 用于連接數據庫的用戶 |
| password | String | 用于連接數據庫的口令 |
連接池實現要求一些額外的配置屬性,它們在 Table 31-5 顯示。
Table 31-5. 額外的連接池DataSource配置屬性
| 屬性 | 類型 | 描述 |
|---|---|---|
| dataSourceName | String | 每一個連接池 DataSource 必須有一個唯一的名字 |
| initialConnections | int | 連接池初始化的時候要創建的數據庫連接數目 |
| maxConnections | int | 允許打開的最大數據庫連接個數。如果請求了更多的連接, 那麼調用者將掛起,直到有一個連接返回給連接池。 |
Example 31-9 顯示了一個使用連接池 DataSource 的典型應用的代碼:
Example 31-9. DataSource 代碼例子
初始化連接池DataSource的代碼例子看起來會象這樣:
Jdbc3PoolingDataSource source = new Jdbc3PoolingDataSource();
source.setDataSourceName("A Data Source");
source.setServerName("localhost");
source.setDatabaseName("test");
source.setUser("testuser");
source.setPassword("testpassword");
source.setMaxConnections(10);然後使用來自連接池的代碼看起來會象這樣。 請注意最終要關閉連接是非常關鍵的,否則這個池子就會"洩漏"連接, 最後把所有客戶端都鎖在外面。
Connection con = null;
try {
con = source.getConnection();
// 使用連接
} catch (SQLException e) {
// 記錄錯誤
} finally {
if (con != null) {
try { con.close(); } catch (SQLException e) {}
}
}
所有 ConnectionPoolDataSource 和 DataSource 實現都可以存儲在 JNDI 裡。在非連接池的實現中, 每次從 JNDI 中檢索對象都將創建一個新的實例, 帶有和存儲的實例同樣的設置。對于連接池實現而言,同一個實例是在可得的情況下檢索出來的(也就是說,沒有其它 JVM 從 JNDI 中檢索連接池),否則就創建同樣設置的新的實例。
在應用服務器環境,通常是應用服務器的 DataSource 實例將存儲在 JNDI 中,而不是 PostgreSQL ConnectionPoolDataSource 的實現。
在應用服務器環境,應用可以在 JNDI 中存儲 DataSource, 這樣它就不用制作一個指向 DataSource 的引用提供給 所有可能需要的應用組件使用它。一個這方面的例子在 Example 31-10 給出。
Example 31-10. DataSource JNDI 代碼例子
初始化連接池DataSource並且把它加到 JNDI 的代碼看起來可能象這樣:
Jdbc3PoolingDataSource source = new Jdbc3PoolingDataSource();
source.setDataSourceName("A Data Source");
source.setServerName("localhost");
source.setDatabaseName("test");
source.setUser("testuser");
source.setPassword("testpassword");
source.setMaxConnections(10);
new InitialContext().rebind("DataSource", source);然後,使用來自連接池的代碼看起來像這個樣子:
Connection con = null;
try {
DataSource source = (DataSource)new InitialContext().lookup("DataSource");
con = source.getConnection();
// 使用連接
} catch (SQLException e) {
// 記錄錯誤
} catch (NamingException e) {
// 在 JNDI 裡沒有找到 DataSource
} finally {
if (con != null) {
try { con.close(); } catch (SQLException e) {}
}
}