Every JDBC 4 compliant driver has a file in its jar called META-INF/services/java.sql.Driver
, in that file it will list its implementation(s) of java.sql.Driver
. When you request a connection, DriverManager
will use the ServiceLoader
to find all(!) copies of META-INF/services/java.sql.Driver
in the classpath and will then load all classes listed. When a java.sql.Driver
class is loaded, it has to register itself with the DriverManager
, so the DriverManager
loads all classes using the service loader, and each Driver
implementation registers itself.
When you request a connection from DriverManager
, the DriverManager
will iterate over all registered drivers asking them for a Connection
. The driver will use the JDBC url to check if it's a protocol it supports (eg Jaybird/Firebird JDBC checks if the url starts with "jdbc:firebirdsql:"
or "jdbc:firebird:"
). If the driver does not support the protocol, it will return null
, if it does support the protocol it will either return an established connection, or it will throw an SQLException
(eg if you made an error in the URL, or it couldn't connect). If all drivers return null
(none support the protocol), then DriverManager
will throw an SQLException
with error "No suitable driver found for <url>"
So, having multiple drivers on the classpath does not matter as long as they support different protocols, however if there are multiple drivers for the same database (or at least: same protocol prefixes), it will use the first in the list of drivers. Depending on the Java version, if that driver fails with an SQLException
, it will continue with the next driver (at least Java 5 and later), or stop trying and throw the exception (I believe this was in Java 1.4 or maybe even earlier).