24.6.13

How JDBC URLs get mapped to connections at runtime

 
How the DriverManager translates a url into a concrete Driver class implementation.

Who cares?

I recently found the need to mock out a JDBC url to experiment with a new way of testing sqoop without a hard dependency on a particular database installation.  In order to do this, you first need to understand how it is that, at runtime, JDBC drivers connection call URLs get routed to implementation specific drivers.


How do JDBC URL's get converted to implementation specific class implementations of the java.sql.Driver interface?

We've all used the canonical JDBC connect snippet for connecting to relational databases from the JVM.


Connection conn = null;
Statement stmt = null;
try{
      Class.forName("com.<database_vendor>.jdbc.Driver");
      conn = DriverManager.getConnection(DB_URL,USER,PASS);
      stmt = conn.createStatement();
      ... 
}
  
What is this code actually doing?

A quick look at the DriverManager class reveals that when we call "getConnection", a data structure is scanned for available drivers which parses out the connection URL:

SQLException reason = null;
for (int i = 0; i < drivers.size(); i++) {
   DriverInfo di = (DriverInfo)drivers.elementAt(i);
   ... 
   if (di.driver.acceptsURL(url)) {
                    // Success!
                    println("getDriver returning " + di);
                    return (di.driver);
   }
}

So... how do the "drivers" get populated ?   

It turns out that the magic  call to:

Class.forName("com.mysql.jdbc.Driver") 

Actually induces a static initialization block (any time a class is loaded, any static code in it gets executed).  So, the JDBC Driver implementations have an soft requirement associated with them which is that they call:

java.sql.DriverManager.registerDriver(new ClientDriverImplementation())

Where the implementation actually implements the "acceptsURL" method.  The below is an excerpt from the derby JDBC driver (similar blocks exist in com.mysql.jdbc.Driver, etc...)

static {
... 
  registeredDriver__ = new ClientDriver(); 
  java.sql.DriverManager.registerDriver(registeredDriver__); 
... 
}

Thanks to the wonderful folks at stack overflow for helping to clarify the static initializer part.   http://stackoverflow.com/questions/5484227/jdbc-class-forname-vs-drivermanager-registerdriver.   

In summary

So.. anyways... the moral of the story is that there is nothing magic about the database connection urls.  You could make your own database connection url as a mock connection with any kind of url text in it, as long as the class.forName(...) method was called in the beggining of your database connection workload, the java.sql.Driver class will be able to figure out what implementation class to map the connection URL to.

1 comment:

  1. Your blog has given me that thing which I never expect to get from all over the websites. Nice post guys!


    melbourne web design

    ReplyDelete