70

Which is the difference from forName method vs registerDriver to load and register a JDBC driver?

xdevel2000
  • 20,780
  • 41
  • 129
  • 196
  • `registerDriver` requires the driver to be available at compile time. Failing so (availability) on runtime would result in NoClassDefFoundError (which you usually would not like to deal with). `Class.forName` implies late binding and doesn't require the driver to be available on compile time. – bestsss Mar 30 '11 at 09:04

3 Answers3

94

Class.forName() is not directly related to JDBC at all. It simply loads a class.

Most JDBC Driver classes register themselves in their static initializers by calling registerDriver().

registerDriver() is the real call that you hardly ever need to call yourself (unless you write your own JDBC driver).

Note that in JDBC 4 you should not need either of those if your JDBC driver is up-to-date, as drivers can be found using the service location mechanisms instead (i.e. simply leave out that call and open your connection as usual). See the documentaton of DriverManager for details:

The DriverManager methods getConnection and getDrivers have been enhanced to support the Java Standard Edition Service Provider mechanism. JDBC 4.0 Drivers must include the file META-INF/services/java.sql.Driver. This file contains the name of the JDBC drivers implementation of java.sql.Driver. For example, to load the my.sql.Driver class, the META-INF/services/java.sql.Driver file would contain the entry:

my.sql.Driver

Applications no longer need to explictly load JDBC drivers using Class.forName(). Existing programs which currently load JDBC drivers using Class.forName() will continue to work without modification.

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
  • 4
    As an example take a look at [MySQL JDBC Driver source code](http://www.docjar.com/html/api/com/mysql/jdbc/Driver.java.html). It calls `registerDriver` in its static initializer. – Piotr Mar 30 '11 at 09:08
  • Ok, but If I use registerDriver than I must load the class into memory? – xdevel2000 Mar 30 '11 at 10:09
  • @xdevel2000: yes. Since `registerDriver()` takes an instance of the `Driver` class as the argument, you must have loaded that class before calling the method. – Joachim Sauer Mar 30 '11 at 11:17
  • Driver d = DriverManager.getDriver("jdbc:mysql://localhost"); do that? – xdevel2000 Mar 30 '11 at 11:55
  • 7
    @xdevel: I don't understand what you're trying to do. If all you want to do is to connect to a database and you've got a sufficiently modern JDBC driver, then you don't need any of `Class.forName()`, `registerDriver` or `getDriver()`. You'd simply call `DriverManager.getConnection("jdbc:mysql://localhost")` without any other preparation. If you want to do something else, then please tell us what that is. – Joachim Sauer Mar 30 '11 at 11:57
  • 2
    Ok, be patient :) my question is only for better understand the JDBC driver registration mechanism. – xdevel2000 Mar 30 '11 at 12:21
  • My case: tomcat 7, java 1.7, postgres jdbc4 with META-INF/services/java.sql.Driver setup, it started working after adding Class.forName() preceding DriverManager.getConnection(). I was able to get tomcat 6, java 1.6, postgres jdbc3 work without calling Class.forName() using JAVA_OPTS -Djdbc.drivers=org.postgresql.Driver that does not seem to work with tomcat 7. Go figure! – Patrick Aug 03 '14 at 19:53
  • @JoachimSauer, Is it true that if we call `.registerDriver` directly, then before that call, the driver's static initializer would run and call `.registerDriver` too, effectively giving us *two* calls to `.registerDriver`? – Pacerier Aug 24 '14 at 21:58
  • 2
    @Pacerier: Yes, I would expect that to happen, and I don't know how the JDBC framework would react to that (I expect it to either ignore the second call or throw an exception on the second call, either way, the driver will be registered). As I wrote in the answer: there is really no reason to call `registerDriver` yourself unless you are writing your own JDBC driver. – Joachim Sauer Aug 24 '14 at 23:02
  • @JoachimSauer, Another post http://stackoverflow.com/a/1311085/632951 seems to claim that calling `registerDriver` twice may give us problems, since we get a *different* instance registered. Anyway, if there is no reason to call `registerDriver`, why is it `public` then? – Pacerier Aug 24 '14 at 23:05
  • 1
    @Pacerier, I don't actually see that claim there. It needs to be public, because drivers aren't magical beasts, they have to follow the same access rules as any other code. If it weren't public they also couldn't call it. Not all rules in an API specification can be encoded using access restrictions (that's true for almost all languages, not just Java). – Joachim Sauer Aug 25 '14 at 22:12
  • You still need to call one of them when running some Java code in an Apache Ant task (except when using the Java task with fork=true) as it uses an already launched JVM and I have found no way to force the scan for (SPI) plugins except for the SPIs on images (see ImageIO.scanForPlugins()). If you find a smarter solution, let me know. – gouessej Apr 03 '18 at 09:30
23

Never call DriverManager.registerDriver() method manually. The JDBC spec requires a driver to register itself when the class is loaded, and the class is loaded via Class.forName(). In JDBC 4 the drivers are able to be loaded automatically just by being on the class path.

DriverManager.registerDriver() manually is potentially dangerous since it actually causes the Driver to be registered twice. If your code requires you to deregister a Driver to prevent a memory leak then you would only end up deregistering it once and leave a second instance registered.

Community
  • 1
  • 1
David O'Meara
  • 2,983
  • 25
  • 38
  • 1
    if you call register, you will need to call deregister (that only normal I guess). Class.forName() has side effects that doesn't deregister the driver. I recall tomcat attempt to deregisters drivers loaded by the webapp on redeploy of the latter. – bestsss Mar 30 '11 at 09:38
  • 1
    No, the `Driver` is required to call `DriverManager.register` itself. If you look at the source for `DriverManager`, calling `register` will add another `Driver` regardless of whether it is already registered. Likewise `deregister` will only remove one instance regardless of how many times it was registered. Short answer: don't do that. – David O'Meara Mar 30 '11 at 10:18
  • @DavidO'Meara, If DriverManager.registerDriver() should never be called directly, why is it a public method? – Pacerier Aug 24 '14 at 21:56
  • @Pacerier It is public because driver implementations need to be able to call it to register themselves. – Mark Rotteveel Sep 18 '14 at 07:24
-2

In additaion to what Joachim Sauer already mentioned about JDBC 4 drivers, note that in practice you usually want to inject either an EntityManager (JPA) or a pooled DataSource (and use JdbcTemplate of Spring).

Puce
  • 37,247
  • 13
  • 80
  • 152
  • Yes, a dependency injection framework. E.g. you could use Java EE: configure the DB in the application server, then inject an EntityManager into your EJB: http://docs.oracle.com/javaee/6/tutorial/doc/bnbqw.html#bnbqz or else you could use Spring: http://static.springsource.org/spring/docs/current/spring-framework-reference/html/jdbc.html – Puce Jun 10 '12 at 10:03
  • There is no mention of Spring or any other frameworks that support injection in the question. – user207421 Feb 25 '22 at 00:37