Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wrong JDBC driver being used?

I have a method that inserts a record into a Postgres DB and returns the identity field generated for said record. The problem is, if I include the Redshift driver in my POM file, that driver is getting used instead of the Postgres driver - and the Redshift driver doesn't allow returning the identity value.

The code is:

try {
  Class.forName( "org.postgresql.Driver" ).newInstance();
  Connection connection = DriverManager.getConnection( "jdbc:postgresql://localhost:5433/postgres", "postgres", "password" );
  Statement stmt = connection.createStatement();
  stmt.execute( "insert into public.job ( job_name ) values ( 'test' )" , Statement.RETURN_GENERATED_KEYS );
  ResultSet keyset = stmt.getGeneratedKeys();
  if ( keyset.next() ) System.out.println( keyset.getLong( 1 ) );
}
catch ( Exception e ) {
  e.printStackTrace();
}

When this POM is used, it works:

<dependencies>
    <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
        <version>9.4-1201-jdbc41</version>
    </dependency>
</dependencies>

When this POM is used, it does not work:

<dependencies>
    <dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>redshift.jdbc</artifactId>
        <version>1.1.2.0002</version>
    </dependency>
    <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
        <version>9.4-1201-jdbc41</version>
    </dependency>
</dependencies>

What is making Java choose the Redshift driver rather than the Postgres driver?

(the Redshift driver's classpath is com.amazon.jdbc41.Driver, so I wouldn't think it's a classpath conflict)

TIA

like image 376
Todd Avatar asked Jul 08 '15 21:07

Todd


People also ask

How do you check JDBC driver is installed or not?

You can determine the version of the JDBC driver that you installed, by calling the getDriverVersion method of the OracleDatabaseMetaData class. You can also determine the version of the JDBC driver by executing the following commands: java -jar ojdbc5. jar.

Which JDBC driver is used?

Type-1 driver or JDBC-ODBC bridge driver uses ODBC driver to connect to the database. The JDBC-ODBC bridge driver converts JDBC method calls into the ODBC function calls. Type-1 driver is also called Universal driver because it can be used to connect to any of the databases.

Which JDBC driver is JDBC-ODBC bridge driver?

The JDBC type 1 driver, also known as the JDBC-ODBC bridge, is a database driver implementation that employs the ODBC driver to connect to the database. The driver converts JDBC method calls into ODBC function calls.

Is JDBC backwards compatible?

JDBC and ADO.NET client drivers are backwards compatible to all Vertica server versions 7.2 and later. The following tables summarize the compatibility of each recent version of the client drivers with the Vertica server versions. The following table indicates that, in general, all clients are forward compatible.


1 Answers

Your problem is, that Java supports the ServiceLoader mechanism with JDBC 4.0.

In JDBC 4, the DriverManager will find and register drivers from the META-INF/services/java.sql.Driver setting in their jar file. When you call getConnection() the DriverManager will choose the first suitable driver for the jdbc URL given.

Now redshift and postgres driver are different in terms of jdbc url, but (quoting from the redshift docs http://docs.aws.amazon.com/redshift/latest/mgmt/configure-jdbc-connection.html#obtain-jdbc-url):

A JDBC URL specified with the former format of jdbc:postgresql://endpoint:port/database will still work.

Now, what happens, is, that the JDBC driver from redshift is loaded over the service entry and places himself as the driver for the redshift jdbc URL and the postgres one.

I cannot tell exactly if the DriverManager allows overwriting existing jdbc-driver-links by loading another driver, but a solution to your problem could be the explicit control to either load the postgres driver first (if URL will be registered only once) or to explicitly load it after the redshift driver (if JDBC URL mapping can be overwritten).

I cannot tell, if there is a property to disallow the redshift driver to register for the postgres URL.

like image 60
thst Avatar answered Sep 22 '22 08:09

thst