11

I've read here on SO that since java 6 you no longer need to register JDBC Driver using:

Class.forName(JDBC_DRIVER);

because DriverManager uses the path located in system property "jdbc.drivers" to retrieve the correct driver.

But when I do the followng:

System.out.print(System.getProperty("jdbc.drivers"));

null gets printed.

Do you have any clue why my app works correctly ?? ;)

GionJh
  • 2,742
  • 2
  • 29
  • 68
  • 2
    It's all explained in the documentation: http://docs.oracle.com/javase/7/docs/api/java/sql/DriverManager.html – JB Nizet Jan 29 '15 at 17:24

2 Answers2

14

That has nothing to do with that system property. Java6 (and JDBC4) introduced a concept known as "service provider" where implementations of known interface can be detected by the JVM during startup. A driver that is compliant with that will be registered by the DriverManager automatically. That's why Class.forName() is no longer necessary - but only if the driver supports that.

The service registration is initiated if there is a services directory in the driver's jar file inside the META-INF directory. That directory needs to contain a text file with the name of the interface that is implemented in the case of a JDBC driver that is java.sql.Driver containing the implementing class.

  • 1
    That means that all I have to do is indicate my JDBC jar implementation , right ? what if I indicate more JDBC implementation ? – GionJh Jan 29 '15 at 17:30
  • 2
    @user986437 Yes, adding a JDBC 4 driver on the classpath is enough. I haven't tried with multiple drivers, but I guess the correct one will be picked dependent on the URL provided (every driver supports a different URL). – Puce Jan 29 '15 at 17:32
  • 1
    It's JDBC 4 not JDBC 3, which introduced that mechanim; http://docs.oracle.com/javase/8/docs/api/java/sql/package-summary.html#package.description – Puce Jan 29 '15 at 17:35
  • 1
    @user986437 Multiple JDBC implementations are not a problem, as long as they use a different JDBC-protocol url-prefix (eg jdbc:mysql, jdbc:firebirdsql, jdbc:postgresql etc). – Mark Rotteveel Jan 30 '15 at 08:44
3

From the Javadocs of DriverManager:

As part of its initialization, the DriverManager class will attempt to load the driver classes referenced in the "jdbc.drivers" system property. This allows a user to customize the JDBC Drivers used by their applications. For example in your ~/.hotjava/properties file you might specify:

jdbc.drivers=foo.bah.Driver:wombat.sql.Driver:bad.taste.ourDriver

This means that the system property need not be specified (as it says DriverManager will attempt). There is another mechanism through which drivers are automatically loaded, which relies on service loading since Java 6:

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.

Almost all JDBC drivers now conform to this requirement. Note that DriverManager does not internally fill the jdbc.drivers property, so it's still null.

Community
  • 1
  • 1
M A
  • 71,713
  • 13
  • 134
  • 174
  • You shouldn't call the `registerDriver` method yourself, it is intended to be called by the JDBC driver implementation itself when it is loaded. The only real exception is if you use a driver that doesn't register itself (and almost all JDBC drivers register themselves when loaded, maybe with the exception of special-purpose (not mainstream) drivers). – Mark Rotteveel Jan 30 '15 at 08:42
  • "This means that the system property should be specified. " - That is not correct if using a JDBC 4 driver, and the behavior described in the question suggests that he/she is using a JDBC 4 driver. – Jeff Scott Brown Nov 21 '19 at 22:11
  • @JeffScottBrown that was indeed badly formulated. It was more like the system property would have to be specified for it to print as not null -- It's corrected now. – M A Nov 25 '19 at 12:39