In this article we delve into the details of a DriverManager and how it manages to locate the appropriate Driver class to establish database connection.
Database connection
The database driver is responsible to establish connection to the database. An application should not instantiate a driver class directly and instead should let the driverManager return a connection.Connection con = DriverManager.getConnection(url)
The URL passed in must contain the necessary details for the driverManager to select the driver from the set of registered drivers.
In the below class diagram, we have three driver classes (DriverOne, DriverTwo and DriverThree).
![]() |
DriverManager |
Registering a driver
In order for the driver to be available to DriverManager, it must be registered. Once registered, it gets added to the internal driver cache of DriverManager.
DriverManager.registerDriver(driverInstance);
Service provider mechanism
Read ServiceLoader to know how service provider mechanism works.
The implementation(s) of Driver are added to the configuration file META-INF/services/java.sql.Driver. Note that the name of the configuration file must be the fully-qualified name of the Driver. When DriverManager is called first time, it finds all the copies of META-INF/services/java.sql.Driver in the classpath. It then loads and instantiates the driver implementations listed in the configuration file.
public class DriverOne implements Driver { private static Driver INSTANCE = new DriverOne(); static { try { DriverManager.registerDriver(INSTANCE); } catch (SQLException e) { //log error } } ... }
Selecting a driver
When we request a connection from DriverManager, it will iterate over all registered drivers asking them for a connection.The driver must implement acceptsURL(url), to make sure the right driver is selected for the JDBC URL.
If it doesn't support the protocol, it must return null so that the DriverManager can try connection with the next driver.
In case of h2 database, the URL must start with jdbc:h2:.
If it does support the protocol it will either return an established connection, or it will throw an SQLException.
In case of h2, if URL is jdbc:default:connection, it will return the default connection.
public class DriverOne implements Driver { private static Driver INSTANCE = new DriverOne(); static { try { DriverManager.registerDriver(INSTANCE); } catch (SQLException e) { //log error } } @Override public Connection connect(String url, Properties info) throws SQLException { if (!acceptsURL(url)) { return null; } return DEFAULT_CONNECTION; } @Override public boolean acceptsURL(String url) throws SQLException { return url.startsWith("jdbc:driverOne:"); } ... }
DriverTwo
public class DriverTwo implements Driver { .. static { try { DriverManager.registerDriver(INSTANCE); } catch (SQLException e) { //log error } } .. }
Suppose we register DriverOne and DriverTwo, both will be available in the cache of DriverManager. We won't register DriverThree so it won't be available in the cache.
public void testRegisteredDrivers() { Enumerationdrivers = DriverManager.getDrivers(); while(drivers.hasMoreElements()) { Driver driver = drivers.nextElement(); assertTrue(driver instanceof JdbcOdbcDriver || driver instanceof DriverOne || driver instanceof DriverTwo); } }
Test case to get DriverOne.
public void testDriverOne() throws SQLException { Driver driverOne = DriverManager.getDriver("jdbc:driverOne:"); assertTrue(driverOne instanceof DriverOne); }
SQLException
If URL is null or there is an error in the URL, an SQLException will be thrown.If all drivers return null, that is none support the protocol, an SQLException will be thrown with error "No suitable driver found for ${url}"
public void testNoSuitableDriverSqlException() { try { DriverManager.getDriver("invalid"); fail("No driver for this URL, should have thrown exception!"); } catch (SQLException e) { //expected } }Home
No comments:
Post a Comment