0

官方 Sybase jConnect 程序员参考建议使用以下方式使用池连接:

SybConnectionPoolDataSource connectionPoolDataSource = new SybConnectionPoolDataSource();
...
Connection ds = connectionPoolDataSource.getConnection();
...
ds.close();

但是 getDataSource 总是会导致异常。我反编译了SybConnectionPoolDataSource,发现方法调用显式产生了错误:

public Connection getConnection() throws SQLException
{
    ErrorMessage.raiseError("JZ0S3", "getConnection()");
    return null;
}

有谁知道为什么文档与实施相矛盾?

4

1 回答 1

3

我不能专门针对 Sybase 发表评论,因为 1)我不使用它,并且 2)您的链接不起作用,但我可以根据自己维护 JDBC 驱动程序的经验(Jaybird/Firebird JDBC)尝试给您一个理论) 并查看其他一些实现的作用。

ConnectionPoolDataSource可能是 JDBC API 中最不被理解的部分。与命名所暗示的内容以及它在某些 JDBC 实现中的实现方式相反,此接口不应该提供连接池,也不应该实现DataSource(或者至少:这样做会导致混乱和错误;我自己的经验)。

的 javadocConnectionPoolDataSource不是很有帮助,javax.sql包文档提供了更多信息,但是您确实需要查看 JDBC 4.1 规范,第 11 章连接池以很好地了解它应该如何工作:

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

换句话说:ConnectionPoolDataSource不是供开发人员直接使用,而是由应用程序服务器用作其连接池;它本身不是连接池。

应用程序服务器为其客户端提供DataSource接口的实现,使连接池对客户端透明。

因此,连接池通过正常DataSource实现对用户可用。用户将其用作不提供池的连接,并使用获得的连接,就好像它是普通的物理连接一样,而不是从连接池中获得的连接:

当应用程序使用完一个连接后,它会使用 方法关闭逻辑连接Connection.close。这会关闭逻辑连接,但不会关闭物理连接。而是将物理连接返回到池中,以便可以重复使用。

连接池对客户端是完全透明的:客户端获得一个池连接并使用它,就像它获得和使用非池连接一样。

PooledConnection(由 a 创建的对象)的文档进一步支持了这一点ConnectionPoolDataSource

应用程序员不PooledConnection直接使用接口;相反,它由管理连接池的中间层基础设施使用。

当应用程序调用该方法DataSource.getConnection时,它会返回一个Connection对象。如果正在执行连接池,则该Connection对象实际上是一个PooledConnection对象的句柄,它是一个物理连接。

连接池管理器(通常是应用程序服务器)维护PooledConnection对象池。如果PooledConnection池中有可用的对象,则连接池管理器返回一个Connection对象,该对象是该物理连接的句柄。如果没有PooledConnection可用的对象,则连接池管理器调用该ConnectionPoolDataSource方法getPoolConnection来创建新的物理连接。JDBC 驱动程序实现ConnectionPoolDataSource创建一个新PooledConnection对象并返回一个句柄。

不幸的是,一些 JDBC 驱动程序已经创建了数据源,这些数据源通过在单个类中实现两者来提供连接池,而不是 JDBC 规范DataSource的意图是使用. 这导致实现如果用作 normal 可以工作,但如果用作 a (例如在应用程序服务器的连接池中),或者接口被误解以及用于创建连接的方法错误(例如打电话)。ConnectionPoolDataSourceDataSourceConnectionPoolDataSourceDataSourceConnectionPoolDataSourcegetPooledConnection().getConnection()

我已经看到了实现(包括在 Jaybird 中),其中getPooledConnection()将用于访问实现内部的连接池,或者只有从getConnection()实现中获得的连接才能正常工作,导致实现时出现各种奇怪和不正确的行为用于填充应用程序服务器中的连接池,使用getPooledConnection().

也许 Sybase 做了类似的事情,然后认为这不是一个好主意,所以他们更改了DataSource.getConnection()抛出异常以确保它不以这种方式使用,但同时通过不删除定义的方法DataSource。或者也许他们扩展了一个普通DataSource的以轻松创建物理连接(而不是包装一个普通的连接),但不希望用户将其用作DataSource.

于 2013-04-09T18:58:02.140 回答