5

一个现有的问题表达了类似的东西,但我想在这里指出一个稍微不同的细微差别。

基本问题:当您定义连接池时,所有应用程序服务器都能够为(little-d,little-s)数据源指定标准)接口和(供应商提供的)实现类。如果供应商为 aConnectionPoolDataSource和常规 ol'提供了实现DataSource,那么哪个是首选?

对于实现DataSource,ConnectionPoolDataSource并且XADataSource在同一个实现类中的供应商实现呢?

文档javax.sql.ConnectionPoolDataSource说,几乎总而言之:

PooledConnection 对象的工厂。实现此接口的对象通常会向基于 JavaTM 命名和目录接口 (JNDI) 的命名服务注册。

这基本上没用,但值得注意的是javax.sql.ConnectionPoolDataSource它本身并不扩展javax.sql.DataSource,这意味着它的实现不需要提供getConnection()方法,这是大多数调用者习惯使用的方法。这告诉我所有应用程序服务器必须:

  • 用一个实现包装一个javax.sql.ConnectionPoolDataSource实现,javax.sql.DataSource以便调用者可以使用javax.sql.DataSource#getConnection(), 或

  • 检测到一个javax.sql.ConnectionPoolDataSource实现也是一个javax.sql.DataSource实现,并且(以某种方式)相信它的getConnection()方法将委托给getPooledConnection()(他们到底将如何做到这一点?)

的文档javax.sql.DataSource部分说:

DataSource 接口由驱动程序供应商实现。有三种类型的实现:

  • 基本实现——产生一个标准的 Connection 对象
  • 连接池实现——生成一个将自动参与连接池的连接对象。此实现与中间层连接池管理器一起使用。
  • 分布式事务实现——生成一个可用于分布式事务并且几乎总是参与连接池的 Connection 对象。此实现与中间层事务管理器一起使用,并且几乎总是与连接池管理器一起使用。

这也是无用的,并且启动不正确(或至少未指定:javax.sql.DataSource也由应用程序服务器供应商实现,他们必须提供一个实现,以便客户端代码可以(例如)将 ajavax.sql.DataSource注入他们的服务器端代码)。这似乎也暗示任何给定的实现可能会或可能不会提供连接池DataSource,这让我想知道应用程序服务器应该如何判断何时设置了指定javax.sql.DataSource接口(而不是javax.sql.ConnectionPoolDataSource接口)的连接池.

注意:我不是在这里寻找关于我在 Tomcat 上是如何做到的,或者我在 GlassFish 上采取的对我有用的步骤或任何类似性质的答案。我正在寻找一个参考 JDBC 规范、Java EE 规范或错误报告的答案,或者表明这些单独(不相关!)接口存在的原因,以及它们应该如何统一或区分的内容在通用 Java EE 应用程序服务器上,因此有义务提供连接池。

4

2 回答 2

0

只是为了说明一下:我正在使用 Postgres,来自 PGConnectionPoolDataSource 的 API 文档对我来说非常清楚:

public class PGConnectionPoolDataSource
extends org.postgresql.ds.jdbc4.AbstractJdbc4ConnectionPoolDataSource
implements javax.sql.ConnectionPoolDataSource

ConnectionPoolDataSource 的 PostgreSQL 实现。应用服务器或中间件供应商应提供利用此 ConnectionPoolDataSource 的 DataSource 实现。如果没有,您可以使用 称为 PoolingDataSource 的 PostgreSQL 实现,但 仅当您的服务器或中间件供应商不提供他们自己的时才应使用。为什么?服务器可能希望在同一事务中请求连接的所有 EJB 中重用相同的连接,或者提供其他类似的高级特性。

于 2014-04-15T14:58:01.447 回答
0

您不应该ConnectionPoolDataSource直接使用 a,它旨在作为物理连接(又名PooledConnections)的源,然后由DataSource实际实现连接池的 a 使用。AConnectionPoolDataSource实际上不应该自己实现池化。

例如,这样的 DataSource 由您的应用程序服务器提供。它通常需要一个 JNDI url(或直接引用)到ConnectionPoolDataSource,并且它本身公开DataSource接口以分发“逻辑”连接。

DataSources 在JDBC 4.1第 9.4 节中讨论:

DataSource 接口 [..] 是获得数据源连接的首选方法。

逻辑名称通过使用 Java Naming and Directory InterfaceTM (JNDI) 的命名服务映射到 DataSource 对象。DataSource 对象代表一个物理数据源并提供与该数据源的连接。

如果我们再看一下介绍中对连接池(第 11 章)的描述,指定:

JDBC 驱动程序提供了 ConnectionPoolDataSource 的实现,应用程序服务器使用它来构建和管理连接池。

用于管理连接池的算法是特定于实现的,并且因应用服务器而异。应用程序服务器为其客户端提供 DataSource接口的实现,该接口使连接池对客户端透明。结果,客户端在使用与以前相同的 JNDI 和 DataSource API 时获得了更好的性能和可伸缩性。(强调我的)

(AS) DataSource(以下简称:ASDS)和(司机)ConnectionPoolDataSource(以下简称 CPDS)之间的交互在第 11.1 - 11.3 节中进行了描述。11.3 节具体描述了交互:

以下步骤序列概述了当 JDBC 客户端从实现连接池的 DataSource 对象请求连接时发生的情况:

  • 客户端调用 DataSource.getConnection。
  • 提供 DataSource 实现的应用程序服务器在其连接池中查看是否有合适的 PooledConnection 对象——一个物理数据库连接——可用​​。确定给定 PooledConnection 对象的适用性可能包括匹配客户端的用户身份验证信息或应用程序类型以及使用其他特定于实现的标准。与管理连接池相关的查找方法和其他方法特定于应用程序服务器。
  • 如果没有合适的 PooledConnection 对象可用,应用服务器调用 ConnectionPoolDataSource.getPooledConnection 方法来获取新的物理连接。实现 ConnectionPoolDataSource 的 JDBC 驱动程序创建一个新的 PooledConnection 对象并将其返回给应用程序服务器。
  • 无论 PooledConnection 是从池中检索到的还是新创建的,应用程序服务器都会进行一些内部记录以指示物理连接现在正在使用中。
  • 应用服务器调用方法 PooledConnection.getConnection 来获取逻辑 Connection 对象。这个逻辑 Connection 对象实际上是物理 PooledConnection 对象的“句柄”,当连接池生效时,DataSource.getConnection 方法返回的正是这个句柄。
  • 应用服务器通过调用方法 PooledConnection.addConnectionEventListener 将自己注册为 ConnectionEventListener。这样做是为了在 PooledConnection 对象可供重用时通知应用程序服务器。
  • 逻辑 Connection 对象返回给 JDBC 客户端,它使用与基本 DataSource 案例中相同的 Connection API。请注意,在客户端调用 Connection.close 方法之前,不能重用底层的 PooledConnection 对象。

最后一项并不完全正确:ASDS 可以通过分发从客户端Connection获得的新连接来强制关闭/无效来自客户端的逻辑连接PooledConnection(参见第 11.4 节)。

现在在评论中提出您的问题:为什么 AS 允许您在数据源配置中同时指定 aDataSourceConnectionPoolDataSourceinterface:ASDS 和 CPDS 之间的引用通常也通过 JNDI 完成。例如,这允许轻松重新配置(将 ASDS 切换到不同的底层 CPDS,或将 ASDS 切换到正常的基本数据源,同时仍保持 CPDS 的配置,例如因为它也被不同的 ASDS 使用)。另请参阅 JDBC 规范的第 11.5 节:

部署实现连接池的 DataSource 对象要求客户端可见的 DataSource 对象和底层 ConnectionPoolDataSource 对象都注册到基于 JNDI 的命名服务。

于 2012-10-11T07:32:16.143 回答