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

Tod*_*odd 5 java jdbc postgresql-9.3

我有一种方法可以将记录插入 Postgres 数据库并返回为所述记录生成的标识字段。问题是,如果我在 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();
}
Run Code Online (Sandbox Code Playgroud)

当使用这个 POM 时,它的工作原理是:

<dependencies>
    <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
        <version>9.4-1201-jdbc41</version>
    </dependency>
</dependencies>
Run Code Online (Sandbox Code Playgroud)

当使用这个 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>
Run Code Online (Sandbox Code Playgroud)

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

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

TIA

ths*_*hst 3

你的问题是,Java 支持ServiceLoaderJDBC 4.0 的机制。

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

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

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

现在,发生的情况是,redshift 的 JDBC 驱动程序通过服务条目加载,并将其自身设置为 redshift jdbc URL 和 postgres 的驱动程序。

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

我无法判断是否有属性禁止 redshift 驱动程序注册 postgres URL。