jConnect4池连接无法记录

时间:2013-04-09 08:23:57

标签: jdbc sybase jconnect

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;
}

有没有人知道文档为何与实现相矛盾?

1 个答案:

答案 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驱动程序通过在单个类中实现DataSourceConnectionPoolDataSource来创建提供连接池的数据源,而不是具有{{1的JDBC规范的意图那个使用一个DataSource。这导致实现如果用作普通ConnectionPoolDataSource将起作用,但如果用作DataSource(例如在应用程序服务器的连接池中),或者接口被误解,则会中断。用于创建连接的错误方法(例如,调用ConnectionPoolDataSource)。

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

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