使用了错误的JDBC驱动程序?

时间:2015-07-08 21:32:47

标签: java jdbc postgresql-9.3

我有一个方法将记录插入Postgres DB并返回为所述记录生成的标识字段。问题是,如果我在我的POM文件中包含Redshift驱动程序,则会使用该驱动程序而不是Postgres驱动程序 - 并且Redshift驱动程序不允许返回标识值。

代码是:

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();
}

使用此POM时,它可以正常工作:

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

使用此POM时,它不起作用:

<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>

是什么让Java选择Redshift驱动程序而不是Postgres驱动程序?

(Redshift驱动程序的类路径是 com.amazon.jdbc41.Driver ,所以我不认为这是类路径冲突)

TIA

3 个答案:

答案 0 :(得分:3)

我能够以正确的顺序一致地加载驱动程序的唯一方法是添加:

format

这是非常重要的,但能完成工作。

答案 1 :(得分:2)

您的问题是,Java支持JDBC 4.0的ServiceLoader机制。

在JDBC 4中,DriverManager将在其jar文件中的META-INF/services/java.sql.Driver设置中查找并注册驱动程序。当您调用getConnection()时,DriverManager将为给定的jdbc URL选择第一个合适的驱动程序。

现在redshift和postgres驱动程序在jdbc url方面有所不同,但是(引用来自redshift docs http://docs.aws.amazon.com/redshift/latest/mgmt/configure-jdbc-connection.html#obtain-jdbc-url):

  

使用以前格式的jdbc指定的JDBC URL:postgresql:// endpoint:port / database仍然有效。

现在,发生的事情是,来自redshift的JDBC驱动程序是通过服务条目加载的,并将自己作为redshift jdbc URL和postgres的驱动程序。

我无法确切地说DriverManager是否允许通过加载另一个驱动程序来覆盖现有的jdbc-driver-links,但是问题的解决方案可能是显式控制要么首先加载postgres驱动程序(如果URL将是只注册一次)或者在redshift驱动程序之后显式加载它(如果可以覆盖JDBC URL映射)。

我不知道,是否有一个属性禁止redshift驱动程序注册postgres URL。

答案 2 :(得分:0)

如下所述,PGDatasource也使用DriverManger,但可以直接创建org.postgresql.jdbc4.Jdbc4Connection

Properties info = new Properties();
info.put("password", "postgres");
Jdbc4Connection c = new Jdbc4Connection(new HostSpec[]{new HostSpec("localhost", 5432)}, "postgres", "postgres", info, "");