Official Sybase jConnect Programmers Reference建议采用以下方法来使用池化连接:
SybConnectionPoolDataSource connectionPoolDataSource = new SybConnectionPoolDataSource();
...
Connection ds = connectionPoolDataSource.getConnection();
...
ds.close();
但是getDataSource总是会导致异常。我反编译SybConnectionPoolDataSource并发现方法调用显式生成错误:
public Connection getConnection() throws SQLException
{
ErrorMessage.raiseError("JZ0S3", "getConnection()");
return null;
}
有没有人知道文档为何与实现相矛盾?
答案 0 :(得分:3)
我不能专门针对Sybase做出评论,因为1)我不使用它2)你的链接不起作用,但我可以尝试根据我自己维护JDBC驱动程序的经验给你一个理论(Jaybird) / Firebird JDBC)并查看其他一些实现的功能。
ConnectionPoolDataSource
可能是JDBC API中最不了解的部分。与命名建议以及如何在某些JDBC实现中实现它相反,此接口不应该提供连接池并且不应该实现DataSource
(或者至少:这样做会导致混淆和错误; 我自己的经验)。
ConnectionPoolDataSource
的javadoc不是很有帮助,javax.sql
包文档提供了更多信息,但你真的需要查看JDBC 4.1规范,第11章 Connection汇集以了解它应该如何运作:
[...] JDBC驱动程序提供了应用程序服务器用于构建和管理连接池的
ConnectionPoolDataSource
实现。
换句话说:ConnectionPoolDataSource
不是供开发人员直接使用,而是由应用程序服务器用于其连接池;它本身不是连接池。
应用程序服务器为其客户端提供
DataSource
接口的实现,使得连接池对客户端透明。
因此,通过正常的DataSource
实现,用户可以使用连接池。用户使用它,因为它不会提供池,并使用获得的连接,就好像它是正常的物理连接而不是从连接池获得的连接:
当使用连接完成应用程序时,它会使用方法
Connection.close
关闭逻辑连接。这会关闭逻辑连接但不会关闭物理连接。而是将物理连接返回到池中,以便可以重用它。连接池对客户端完全透明:客户端获取池连接,并以与获取和使用非池连接相同的方式使用它。
PooledConnection
(由ConnectionPoolDataSource
创建的对象)的文档进一步支持了这一点:
应用程序员不直接使用
PooledConnection
接口;相反,它由管理连接池的中间层基础结构使用。当应用程序调用方法
DataSource.getConnection
时,它会返回Connection
个对象。如果正在进行连接池,则Connection
对象实际上是PooledConnection
对象的句柄,这是一个物理连接。连接池管理器(通常是应用程序服务器)维护一个
PooledConnection
个对象池。如果池中有可用的PooledConnection
对象,则连接池管理器将返回Connection
对象,该对象是该物理连接的句柄。如果没有PooledConnection
对象可用,则连接池管理器会调用ConnectionPoolDataSource
方法getPoolConnection
来创建新的物理连接。实现ConnectionPoolDataSource
的JDBC驱动程序创建一个新的PooledConnection
对象并返回一个句柄。
不幸的是,一些JDBC驱动程序通过在单个类中实现DataSource
和ConnectionPoolDataSource
来创建提供连接池的数据源,而不是具有{{1的JDBC规范的意图那个使用一个DataSource
。这导致实现如果用作普通ConnectionPoolDataSource
将起作用,但如果用作DataSource
(例如在应用程序服务器的连接池中),或者接口被误解,则会中断。用于创建连接的错误方法(例如,调用ConnectionPoolDataSource
)。
我见过实现(包括在Jaybird中),其中getPooledConnection().getConnection()
将用于访问实现内部的连接池,或者只有从实现的getPooledConnection()
获得的连接才能正常工作当使用getConnection()
将该实现用于填充应用程序服务器中的连接池时,会导致各种奇怪和不正确的行为。
也许Sybase做了类似的事情,然后决定这不是一个好主意,所以他们改变了getPooledConnection()
以抛出异常,以确保它没有以这种方式使用,但同时通过不删除DataSource.getConnection()
定义的方法来维护API兼容性。或者他们可以扩展正常DataSource
以轻松创建物理连接(而不是包装正常连接),但不希望用户将其用作DataSource
。