Redshift和Postgres JDBC驱动程序都拦截了jdbc:// postgresql连接字符串

时间:2015-08-11 20:39:46

标签: java spring postgresql jdbc amazon-redshift

我有一个问题,我不太确定如何解决:我有一个Web应用程序(打包为战争),客户端可以配置他们希望指向哪个数据库。我们支持PostgreSQL和Redshift(以及其他)。 JDBC4驱动程序是自动加载的,这很好。这就是问题所在:

似乎Redshift JDBC驱动程序将在PostgreSQL之前响应jdbc:// postgresql连接字符串。连接到PostgreSQL数据库时,这会导致JDBC错误。

我正在指定驱动程序名称' org.postgresql.Driver'作为我的pom.xml中数据源的驱动程序,但我不确定spring JDBC模板是如何选择驱动程序的(除非它拿起第一个处理程序)。

其他人遇到过这类问题吗?

3 个答案:

答案 0 :(得分:14)

另一个解决方案是添加" OpenSourceSubProtocolOverride = true"到常规PostgreSQL连接的JDBC连接字符串。

示例:

jdbc:postgresql://localhost:5432/postgres?OpenSourceSubProtocolOverride=true  

答案 1 :(得分:4)

这是因为redshift驱动程序注册为能够同时处理jdbc:postgresqljdbc:redshift URL前缀。

当Postgres& Redshift驱动程序从他们各自向DriverManger注册的罐子中加载。

DriverMananger.getDriver()DriverManager.getConnection()中实现的逻辑是循环遍历每个驱动程序,并在驱动程序指示它能够处理给定的URL时停止。

如果Postgres驱动程序首先注册,一切正常,因为Postgres驱动程序只尝试处理jdbc:postgresql。如果Redshift驱动程序首先注册,那么永远不会使用Postgres驱动程序。

我想出解决这个问题的唯一方法是添加:

static {
    // Put the redshift driver at the end so that it doesn't
    // conflict with postgres queries
    java.util.Enumeration<Driver> drivers =  DriverManager.getDrivers();
    while (drivers.hasMoreElements()) {
        Driver d = drivers.nextElement();
        if (d.getClass().getName().equals("com.amazon.redshift.jdbc41.Driver")) {
            try {
                DriverManager.deregisterDriver(d);
                DriverManager.registerDriver(d);
            } catch (SQLException e) {
                throw new RuntimeException("Could not deregister redshift driver");
            }
            break;
        }
    }
}

答案 2 :(得分:0)

太糟糕了,在解决问题之前我没有看到其他答案,但是我通过这样做来替代Redshift驱动程序中的“ postgres”子协议,从而解决了问题

String[] names = com.amazon.redshift.PGInfo.PG_SUBPROTOCOL_NAMES;
for (int i = 0; i < names.length; i++)
    if (names[i].equals("postgresql"))
        names[i] = UUID.randomUUID().toString(); // Just random string