Reputation: 195
I'm reading JDBC code. In DriverManager.getConnection, I find it works like this: it tries to connect every Driver it knows until it success.
Here is the code:
for(DriverInfo aDriver : registeredDrivers) {
// If the caller does not have permission to load the driver then
// skip it.
if(isDriverAllowed(aDriver.driver, callerCL)) {
try {
println(" trying " + aDriver.driver.getClass().getName());
Connection con = aDriver.driver.connect(url, info);
if (con != null) {
// Success!
println("getConnection returning " + aDriver.driver.getClass().getName());
return (con);
}
} catch (SQLException ex) {
if (reason == null) {
reason = ex;
}
}
} else {
println(" skipping: " + aDriver.getClass().getName());
}
}
But there is a method "acceptsURL" from interface Driver:
boolean acceptsURL(String url) throws SQLException;
So my question is, why DriverManager does not call this method before it do the real connection to filter unrelated drivers?
Or with code, may be this is better?
for(DriverInfo aDriver : registeredDrivers) {
// If the caller does not have permission to load the driver then
// skip it.
if(isDriverAllowed(aDriver.driver, callerCL) && aDriver.driver.acceptsURL(url)) {
try {
println(" trying " + aDriver.driver.getClass().getName());
Connection con = aDriver.driver.connect(url, info);
if (con != null) {
// Success!
println("getConnection returning " + aDriver.driver.getClass().getName());
return (con);
}
} catch (SQLException ex) {
if (reason == null) {
reason = ex;
}
}
} else {
println(" skipping: " + aDriver.getClass().getName());
}
}
Upvotes: 1
Views: 579
Reputation: 109257
The DriverManager
reference implementation (OpenJDK) doesn't use acceptsUrl
. That doesn't necessarily mean there are no DriverManager
implementations using it. In fact, as far as I recall, earlier Sun Java implementations did call acceptsURL
. The main reason it isn't called, is that the JDBC specification requires DriverManager
to call connect
on each registered driver anyway. See below.
Nothing in the specification or API documentation says that DriverManager
must use acceptsURL
. The JDBC 4.3 specification on this only says (section 9.2 The Driver
interface):
The
DriverManager
class invokesDriver
methods when it wishes to interact with a registered driver. TheDriver
interface also includes the methodacceptsURL
. TheDriverManager
can use this method to determine which of its registered drivers it should use for a given URL.
(emphasis mine)
Note the use of the word can instead of must or will.
The subsequent paragraph says:
When the
DriverManager
is trying to establish a connection, it calls that driver’sconnect
method and passes the driver the URL. If theDriver
implementation understands the URL, it will return aConnection
object or throw aSQLException
if a connection cannot be maded [sic] to the database. If theDriver
implementation does not understand the URL, it will returnnull
.
In addition, section 9.4 The DriverManager
class says:
getConnection
— the method the JDBC client invokes to establish a connection. The invocation includes a JDBC URL, which theDriverManager
passes to each driver in its list until it finds one whoseDriver.connect
method recognizes the URL. That driver returns aConnection
object to theDriverManager
, which in turn passes it to the application.
(emphasis mine)
How I read this, calling Driver.connect
on each driver is required anyway, so there is no point for the implementation to call acceptsURL
.
Now, as to why the JDBC specification is written this way, I don't know, and I'm a member of the JSR-221 (JDBC 4) Expert Group myself. When I joined the Expert Group the implementation (and specification) was already this way, so I'm not aware of its history. However, I'm not sure you'll get a better answer here than above unsatisfactory answer (it is so because the specification says so).
However, if I had to guess, it is probably to do with the fact that for some drivers determining if they can accept an URL could be relatively complex or expensive. In that case it is better to just try and connect, because for a driver rejecting the URL the cost is (or should be) the same as just calling acceptsURL
, while for a driver that will actually accept the URL, the cost would be hit twice if DriverManager
would first call acceptsURL
followed by a connect
.
This doesn't mean that the acceptsURL
method is entirely without value. Some applications (eg some query tools or reporting tools) use it to discover which driver(s) would handle a specific URL, so they can interrogate the Driver
implementation(s) for their supported connection properties (Driver.getPropertyInfo
) so they can populate there connection wizard with the available properties. Other programs could use it to get information like its version (Driver.getMajorVersion
, Driver.getMinorVersion
), parent logger (Driver.getParentLogger
) or JDBC compliancy (Driver.jdbcCompliant
).
Upvotes: 4