• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Why use Class.forName() to load driver

 
Ashutosh Limaye
Ranch Hand
Posts: 58
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If we just create a reference of the driver(say: sun.jdbc.odbc.JdbcOdbcDriver) and say new,
the driver gets loaded...also since each driver has a
static block it will register itself with the DriverManager
All the code works fine.

Then why is Class.forName() used to load a driver???
 
anand correia
Greenhorn
Posts: 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The class.forName() is used when we donot know the driver class name, therefore we just pass string name and load class in the memory.

for e.g. class.forName("name")

depending upon "name" it will dynamically load the class and return class provided the class ia available in class path.
 
Stan James
(instanceof Sidekick)
Ranch Hand
Posts: 8791
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The class.forName() causes the ClassLoader to load the class into memory. JDBC driver classes contain a static initializer block that registers the driver with DriverManager for later reference. When you connect DriverManager uses the database parameter to look up the right driver. Here's a connection I use:

The "jdbc: db2:" part of the string matches a driver I loaded earlier.

This is pretty slick, but it's in the non-obvious category. It might have been better for Sun to define a more explicit way of registering drivers. Wait! They did:


Edited: There are no spaces in that "jdbc: db2" string but I put one in to avoid making smileys.
[ March 09, 2006: Message edited by: Stan James ]
 
Jeanne Boyarsky
author & internet detective
Marshal
Posts: 34645
363
Eclipse IDE Java VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Stan James:
Edited: There are no spaces in that "jdbc: db2" string but I put one in to avoid making smileys.

Just want to make sure (and everyone else) know there is a checkbox to disable smilies in a post if you scroll down on the screen where you type in the message. Very useful when posting code!
 
Ashutosh Limaye
Ranch Hand
Posts: 58
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Firslty Thanks for replying

@Anand: I agree that we can load the class with the help of the static
forName() method but the string that you pass to it should still be
Phonetically matching the actual class.So if this is the case then we
already have the class name....just call new on it...

@Stan: The Code:
Driver driver = (Driver) Class.forName("COM.ibm.db2.jdbc.app.DB2Driver").
newInstance();
DriverManager.registerDriver(driver);
is more self-explainatory than:

Class.forName("COM.ibm.db2.jdbc.app.DB2Driver");
Connection con=DriverManager.getConnection(/*URL*/);

That is exactly what I wanted to know...then why is that all the
documentations and tutorials on JDBC suggest the use of second method??
 
stu derby
Ranch Hand
Posts: 333
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator



@Stan: The Code:
Driver driver = (Driver) Class.forName("COM.ibm.db2.jdbc.app.DB2Driver").
newInstance();
DriverManager.registerDriver(driver);
is more self-explainatory than:



... and creates two instance of the driver and registers both of them (which is probably harmless). One instance is created and registerd by the code above and one is creating in the Driver's initialization block.

It's relatively harmless to do it Stan's way, unless for some weird reason the driver breaks if there are 2 instances of the class... that would be a poorly written driver, IMHO.
[ March 09, 2006: Message edited by: stu derby ]
 
Ashutosh Limaye
Ranch Hand
Posts: 58
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
One instance is created and registerd by the code above and one is creating in the Driver's initialization block.


Sorry i didn't get you Stu...
 
Stan James
(instanceof Sidekick)
Ranch Hand
Posts: 8791
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Interesting point, Stu. I copied that from somewhere the first week I tried JDBC and haven't looked at it since. (The power of reusable objects!)

Ashutosh, that makes two instances of the driver because the static initializer makes one instance the first time I reference the class for any reason, and the newInstance() call makes another.

Maybe DriverManager is smart enough to only keep a reference to one of those and the other goes to GC. It seems to work anyhow.
 
Ashutosh Limaye
Ranch Hand
Posts: 58
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Driver driver=new COM.ibm.db2.jdbc.app.DB2Driver();
DriverManager.registerDriver(driver);



Will this work??
 
Joel McNary
Bartender
Posts: 1840
Eclipse IDE Java Ruby
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
@Anand: I agree that we can load the class with the help of the static
forName() method but the string that you pass to it should still be
Phonetically matching the actual class.So if this is the case then we
already have the class name....just call new on it...


You might not already have it. It could be read in from a configuration file (XML/properties file).

As far as the reason that they use static initializers, personally, I think that they just wanted to show off the cool static initializer capabilities of Java. But there could be a more sinister and obtuse reason (although I'm not sure theis fully explains the reason): A specific JDBC driver can only be used in a class that was loaded by the same class loader as the one that loaded the driver.

Hunh? What was that, again? Could you please repeat that?

OK. A specific JDBC driver can only be used in a class that was loaded by the same class loader as the one that loaded the driver. So if Class A was loaded by ClassLoader Z, and you ask for Driver.getConnection("..."), the JDBC driver that matches that URL had better also been loaded by ClassLoader Z -- otherwise you get a no valid driver exception.

So, since Class.forName turns around and calls the *system* classloader, you get the driver loaded in the standard classloader. This is fine, unless you are trying to reference a Driver loaded by a different class loader (or if you are in a class loaded by a non-system classloader).

Granted, calling new JDBCDriverClass() should do the same thing, but there may be differences internally that make the .forName() preferred over the .new(). That, and you don't actually have to create a new instance of the driver.

Now, why they chose to make this distinction based on ClassLoader, I'm not sure. Perhaps someone could try to explain that one.
 
Stan James
(instanceof Sidekick)
Ranch Hand
Posts: 8791
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ashutosh, your sample with new COM.ibm.db2.jdbc.app.DB2Driver() should work. The big difference between my post and that is that you have a compile time dependency on the IBM driver and I wanted to avoid it.

I have a handful of little connector classes for different databases. I move the code between work and home. Work uses one RDBMS and home uses another. Neither machine has all the drivers installed, yet none of the connector classes have any compile problems because the driver classnames are all in strings. Does that makes sense?

Here's a complete example of the concrete classes:

I copied this method of registering drivers from some example code before I knew about the static initializer method. This may well be sub-optimal, but it works just fine for my small scale personal projects.
[ March 11, 2006: Message edited by: Stan James ]
 
Ashutosh Limaye
Ranch Hand
Posts: 58
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That was amazing...!!!
Thanks Joel,Thanks Stan....You people had been a great help...
I think my problem is almost solved..
 
Savio Fernandes
Greenhorn
Posts: 16
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have a question which moves off a little from what's being discussed.

So, it is possible to have more than one driver, for the same database, registered at the same time with the DriverManager, right?

If the above is correct, then how does the DriverManager decide which driver to use, when I call the getConnection() method?
 
Ulf Dittmer
Rancher
Posts: 42968
73
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
By looking at the URL of the connection - each driver handles a specific type of connection URL. If you have different drivers, they would have different URLs.
 
Ashutosh Limaye
Ranch Hand
Posts: 58
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The DriverManager maintains a Table(may be a Map)for all the drivers that are registered.The URL that you pass to the getConnection() acts like the name in a name-value pair, the value is the desired driver.

Hmmm...I'm I making sense?!
 
Raghvendra Tiwari
Greenhorn
Posts: 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Thanks to codereanch and it's all menber....
It really solved my problem....
Thanks Again
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic