问题
Official Sybase jConnect Programmers Reference suggests following way to use pooled connections:
SybConnectionPoolDataSource connectionPoolDataSource = new SybConnectionPoolDataSource();
...
Connection ds = connectionPoolDataSource.getConnection();
...
ds.close();
However getDataSource always causes exception. I decompiled SybConnectionPoolDataSource and found that the method call explicitly generates an error:
public Connection getConnection() throws SQLException
{
ErrorMessage.raiseError("JZ0S3", "getConnection()");
return null;
}
Does anyone have an idea why the documentation contradicts to the implementation?
回答1:
I can't comment specifically for Sybase because 1) I don't use it and 2) your link doesn't work, but I can try to give you a theory based on my own experience maintaining a JDBC driver (Jaybird/Firebird JDBC) and looking at what some of the other implementations do.
The ConnectionPoolDataSource is probably the least understood part of the JDBC API. Contrary to what the naming suggests and how it has been implemented in some JDBC implementations this interface SHOULD NOT provide connection pooling and should not implement DataSource
(or at least: doing that can lead to confusion and bugs; my own experience).
The javadoc of the ConnectionPoolDataSource
is not very helpful, the javax.sql package documentation provides a little bit more info, but you really need to look at the JDBC 4.1 specification, Chapter 11 Connection Pooling to get a good idea how it should work:
[...] the JDBC driver provides an implementation of
ConnectionPoolDataSource
that the application server uses to build and manage the connection pool.
In other words: ConnectionPoolDataSource
isn't meant for direct use by a developer, but instead is used by an application server for its connection pool; it isn't a connection pool itself.
The application server provides its clients with an implementation of the
DataSource
interface that makes connection pooling transparent to the client.
So the connection pool is made available to the user by means of a normal DataSource
implementation. The user uses this as would it be one that doesn't provide pooling, and uses the connections obtained as if it is a normal physical connection instead of one obtained from a connection pool:
When an application is finished using a connection, it closes the logical connection using the method
Connection.close
. This closes the logical connection but does not close the physical connection. Instead, the physical connection is returned to the pool so that it can be reused.Connection pooling is completely transparent to the client: A client obtains a pooled connection and uses it just the same way it obtains and uses a non pooled connection.
This is further supported by the documentation of PooledConnection (the object created by a ConnectionPoolDataSource
):
An application programmer does not use the
PooledConnection
interface directly; rather, it is used by a middle tier infrastructure that manages the pooling of connections.When an application calls the method
DataSource.getConnection
, it gets back aConnection
object. If connection pooling is being done, thatConnection
object is actually a handle to aPooledConnection
object, which is a physical connection.The connection pool manager, typically the application server, maintains a pool of
PooledConnection
objects. If there is aPooledConnection
object available in the pool, the connection pool manager returns aConnection
object that is a handle to that physical connection. If noPooledConnection
object is available, the connection pool manager calls theConnectionPoolDataSource
methodgetPoolConnection
to create a new physical connection. The JDBC driver implementingConnectionPoolDataSource
creates a newPooledConnection
object and returns a handle to it.
Unfortunately, some of JDBC drivers have created data sources that provide connection pooling by implementing both DataSource
and ConnectionPoolDataSource
in a single class, instead of the intent of the JDBC spec of having a DataSource
that uses a ConnectionPoolDataSource
. This has resulted in implementations that would work if used as a normal DataSource
, but would break if used as a ConnectionPoolDataSource
(eg in the connection pool of an application server), or where the interface was misunderstood and the wrong methods where used to create connections (eg calling getPooledConnection().getConnection()
).
I have seen implementations (including in Jaybird) where the getPooledConnection()
would be used to access a connection pool internal to the implementation, or where only connections obtained from the getConnection()
of the implementation would work correctly, leading to all kinds of oddities and incorrect behavior when that implementation was used to fill a connection pool in an application server using the getPooledConnection()
.
Maybe Sybase did something similar, and then decided that wasn't such a good idea so they changed the DataSource.getConnection()
to throw an exception to make sure it wasn't used in this way, but at the same time maintaining the API compatibility by not removing the methods defined by DataSource
. Or maybe they extended a normal DataSource
to easily create the physical connection (instead of wrapping a normal one), but don't want users to use it as a DataSource
.
来源:https://stackoverflow.com/questions/15896872/jconnect4-pooled-connection-does-not-work-as-documented