【问题标题】:Redshift and Postgres JDBC driver both intercept jdbc://postgresql connection stringRedshift 和 Postgres JDBC 驱动程序都拦截 jdbc://postgresql 连接字符串
【发布时间】:2015-11-04 06:05:50
【问题描述】:

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

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

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

还有其他人遇到过这种问题吗?

【问题讨论】:

    标签: java spring postgresql jdbc amazon-redshift


    【解决方案1】:

    另一种解决方案是将“OpenSourceSubProtocolOverride=true”添加到常规 PostgreSQL 连接的 JDBC 连接字符串中。

    例子:

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

    【讨论】:

    【解决方案2】:

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

    当 Postgres 和 Redshift 驱动程序从它们的 jar 中加载时,它们会分别向 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;
            }
        }
    }
    

    【讨论】:

    • 我们正在使用 Spring JDBC 模板,有没有办法为 DataSource 指定应该使用的驱动程序?我以为我在驱动程序管理器上看到了类似 setDriver() 的东西,但我有点像 Spring 菜鸟......
    • 我对spring不熟悉,所以不确定。如果 spring 只是在幕后使用 DriverManager,那么我认为重新排序驱动程序应该可以解决问题。
    【解决方案3】:

    太糟糕了,在我解决问题之前我没有看到其他答案,但我通过这样做覆盖了 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-01-30
      • 1970-01-01
      • 2010-11-30
      • 2013-11-11
      • 2013-10-25
      • 2012-11-15
      • 1970-01-01
      相关资源
      最近更新 更多