How is driver class located in JDBC4
Asked Answered
T

3

12

One of the great additions in version 4 of JDBC You don't have to explicitly load the driver by calling Class.forName anymore. When your application attempts to connect the database for the first time, DriverManager automatically loads the driver found in the application CLASSPATH.

My question is how? What if there are multiple drivers in the classpath?

One thing I can guess is that on parsing the connection URL whether driver needed is of JDBC or ODBC can be figured out but how can one say out of multiple jdbc compliant drivers which one is to be selected for the database I am using? (lets say I am using MySql and I need MySql-Connector driver). Is there any static mapping of such database drivers in JVM?

Tilefish answered 17/8, 2013 at 11:4 Comment(3)
Why do you need a driver?Odaodab
How else would you connect to the database. Traditionally we do Class.ForName(driver).Tilefish
@atamanroman I have nothing to explain to you, keep your jargon out of SO.Odaodab
N
12

Some information about JDBC4 driver loading taken from : http://www.onjava.com/2006/08/02/jjdbc-4-enhancements-in-java-se-6.html

When the method getConnection is called, the DriverManager will attempt to locate a suitable driver from among the JDBC drivers that were loaded at initialization and those loaded explicitly using the same class loader as the current application.

The DriverManager methods getConnection and getDrivers have been enhanced to support the Java SE Service Provider mechanism (SPM). According to SPM, a service is defined as a well-known set of interfaces and abstract classes, and a service provider is a specific implementation of a service. It also specifies that the service provider configuration files are stored in the META-INF/services directory. JDBC 4.0 drivers must include the file META-INF/services/java.sql.Driver. This file contains the name of the JDBC driver's implementation of java.sql.Driver. For example, to load the JDBC driver to connect to a Apache Derby database, the META-INF/services/java.sql.Driver file would contain the following entry:

org.apache.derby.jdbc.EmbeddedDriver

Now coming to your question.

My question is how? What if there are multiple drivers in the classpath?

As a class loader rule, any class found first will be loaded and if it is already loaded then will not be reloaded by the class loader.

Niels answered 17/8, 2013 at 11:6 Comment(0)
S
23

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).

Stalnaker answered 18/8, 2013 at 8:54 Comment(2)
Can we list all the drivers that are already registered on the machine?Manipular
@Manipular Yes, check the API of DriverManager, specifically drivers() and getDrivers() methods.Stalnaker
N
12

Some information about JDBC4 driver loading taken from : http://www.onjava.com/2006/08/02/jjdbc-4-enhancements-in-java-se-6.html

When the method getConnection is called, the DriverManager will attempt to locate a suitable driver from among the JDBC drivers that were loaded at initialization and those loaded explicitly using the same class loader as the current application.

The DriverManager methods getConnection and getDrivers have been enhanced to support the Java SE Service Provider mechanism (SPM). According to SPM, a service is defined as a well-known set of interfaces and abstract classes, and a service provider is a specific implementation of a service. It also specifies that the service provider configuration files are stored in the META-INF/services directory. JDBC 4.0 drivers must include the file META-INF/services/java.sql.Driver. This file contains the name of the JDBC driver's implementation of java.sql.Driver. For example, to load the JDBC driver to connect to a Apache Derby database, the META-INF/services/java.sql.Driver file would contain the following entry:

org.apache.derby.jdbc.EmbeddedDriver

Now coming to your question.

My question is how? What if there are multiple drivers in the classpath?

As a class loader rule, any class found first will be loaded and if it is already loaded then will not be reloaded by the class loader.

Niels answered 17/8, 2013 at 11:6 Comment(0)
T
0

Answer for your question will get it from java.sql.DriverManager java class ,method loadInitialDrivers.

drivers = AccessController.doPrivileged(new PrivilegedAction<String>() {
    public String run() {
                return System.getProperty("jdbc.drivers");
            }
        });  

If program found multiple jdbc driver,it will use below logic to take exact driver

    String[] driversList = drivers.split(":");
    println("number of Drivers:" + driversList.length);
    for (String aDriver : driversList) {
        try {
            println("DriverManager.Initialize: loading " + aDriver);
            Class.forName(aDriver, true,
                    ClassLoader.getSystemClassLoader());
        } catch (Exception ex) {
            println("DriverManager.Initialize: load failed: " + ex);
        } 
Tav answered 28/8, 2020 at 6:20 Comment(1)
This is not the automatic driver loading introduced in JDBC 4.0, but an older (and still supported) mechanism which allow you to specify the driver class names in system property jdbc.drivers.Stalnaker

© 2022 - 2024 — McMap. All rights reserved.