pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
JDBC 2 在一个称为 JDBC 2.0 Optional Package(也称为 JDBC 2.0 Standard Extension)的附加 API 中引入了标准的连接池 特性。这些特性后来被包含在 核心 JDBC 3 API 中。 PostgreSQL JDBC 驱动 在配合 JDBC 2.0 Optional Package(JDBC 2)与 JDK 1.3.x 一起编译,或者与 JDK 1.4 或更高版本(JDBC 3)一起 编译时支持这些特性。大多数应用服务器都包含 JDBC 2.0 Optional Package,它也可以从 Sun 的 JDBC 下载站点单独获得。
JDBC API 为连接池提供了一个 客户端接口和一个 服务器端接口。客户端 接口是 javax.sql.DataSource, 应用代码通常用它来 获取一个池化的数据库连接。服务器端 接口是 javax.sql.ConnectionPoolDataSource, 大多数应用服务器将通过它与 PostgreSQL JDBC 驱动对接。
在应用服务器环境中,应用服务器的配置通常引用 PostgreSQL 的 ConnectionPoolDataSource 实现, 而应用组件代码通常获取由 应用服务器(而不是 PostgreSQL)提供的 DataSource 实现。
对于没有应用服务器的环境, PostgreSQL 提供了应用程序可以直接使用的两种 DataSource 实现。一种实现执行连接池化, 而另一种只是通过 DataSource 接口提供对数据库连接的 访问,不做任何池化。另外,这些实现不应在 应用服务器环境中使用,除非 应用服务器不支持 ConnectionPoolDataSource 接口。
ConnectionPoolDataSource #PostgreSQL 为 JDBC 2 和 JDBC 3 各包含一个 ConnectionPoolDataSource 的实现, 如 表 31.1 所示。
表 31.1. ConnectionPoolDataSource 实现
| JDBC | 实现类 |
|---|---|
| 2 | org.postgresql.jdbc2.optional.ConnectionPool |
| 3 | org.postgresql.jdbc3.Jdbc3ConnectionPool |
两种实现使用相同的配置方案。 JDBC 要求 ConnectionPoolDataSource 通过 JavaBean 属性配置,如 表 31.2 所示, 因此每种属性都有相应的 get 和 set 方法。
表 31.2. ConnectionPoolDataSource 配置属性
| 属性 | 类型 | 描述 |
|---|---|---|
serverName |
String |
PostgreSQL 数据库服务器 的主机名 |
databaseName |
String |
PostgreSQL 数据库名 |
portNumber |
int |
PostgreSQL 数据库服务器监听的 TCP 端口(或者用 0 表示使用默认端口) |
user |
String |
用来建立数据库连接的用户 |
password |
String |
用来建立数据库连接的口令 |
defaultAutoCommit |
boolean |
连接被交给调用方时,其自动提交是启用还是 禁用。默认值为 false,即禁用自动提交。 |
许多应用服务器使用属性风格的语法来 配置这些属性,因此把属性作为一块文本输入并不罕见。如果 应用服务器提供单一区域来输入所有属性,它们可能 像这样列出:
serverName=localhost databaseName=test user=testuser password=testpassword
或者,如果用分号而不是换行符作为分隔符,它可能 像这样:
serverName=localhost;databaseName=test;user=testuser;password=testpassword
DataSource #PostgreSQL 为 JDBC 2 包含两种 DataSource 实现,为 JDBC 3 也包含两种,如 表 31.3 所示。 池化实现在客户端调用 close 方法时实际上并不 关闭连接,而是把连接归还到 一个可供其他客户端使用的空闲连接池中。 这避免了反复打开和关闭连接的任何开销, 并允许大量客户端共享少量数据库连接。
这里提供的池化数据源实现并不是 世界上功能最丰富的。举几个方面:连接直到 池本身关闭之前永远不会被关闭; 没有办法收缩池。而且,为默认配置用户之外的用户 请求的连接不会被池化。许多应用服务器 提供更高级的池化特性,并改用 ConnectionPoolDataSource 实现。
表 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 属性配置,如 表 31.4 所示, 因此每种属性都有相应的 get 和 set 方法。
表 31.4. DataSource 配置属性
| 属性 | 类型 | 描述 |
|---|---|---|
serverName |
String |
PostgreSQL 数据库服务器 的主机名 |
databaseName |
String |
PostgreSQL 数据库名 |
portNumber |
int |
PostgreSQL 数据库服务器监听的 TCP 端口(或者用 0 表示使用默认端口) |
user |
String |
用来建立数据库连接的用户 |
password |
String |
用来建立数据库连接的口令 |
池化实现需要一些额外的 配置属性,它们显示在 表 31.5 中。
表 31.5. 池化 DataSource 的额外配置属性
| 属性 | 类型 | 描述 |
|---|---|---|
dataSourceName |
String |
每个池化 DataSource 都必须有一个 唯一的名称。 |
initialConnections |
int |
池初始化时要创建的 数据库连接数量。 |
maxConnections |
int |
允许的打开数据库连接的最大数量。 当请求更多连接时,调用方将 挂起,直到有连接被归还到池中。 |
例 31.9 展示了使用池化 DataSource 的典型应用代码的一个例子。
例 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();
// use connection
} catch (SQLException e) {
// log error
} finally {
if (con != null) {
try { con.close(); } catch (SQLException e) {}
}
}
所有 ConnectionPoolDataSource 和 DataSource 实现都可以存储 在 JNDI 中。对于非池化 实现,每次从 JNDI 检索该对象时都会 创建一个新实例,其设置与被存储的实例 相同。对于 池化实现,只要它可用(例如,不是从 JNDI 检索该池的另一个不同 JVM),就会检索到同一个实例,否则会 用相同的设置创建一个新实例。
在应用服务器环境中,通常存储在 JNDI 中的是应用服务器的 DataSource 实例,而不是 PostgreSQL 的 ConnectionPoolDataSource 实现。
在应用程序环境中,应用程序可以把 DataSource 存储在 JNDI 中,这样它就不必把对 DataSource 的引用提供给它可能需要 使用它的所有应用 组件。例 31.10 展示了这样的一个 例子。
例 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();
// use connection
} catch (SQLException e) {
// log error
} catch (NamingException e) {
// DataSource wasn't found in JNDI
} finally {
if (con != null) {
try { con.close(); } catch (SQLException e) {}
}
}
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。