我有一个问题,我不太确定如何解决:我有一个Web应用程序(打包为战争),客户端可以配置他们希望指向哪个数据库。我们支持PostgreSQL和Redshift(以及其他)。 JDBC4驱动程序是自动加载的,这很好。这就是问题所在:
似乎Redshift JDBC驱动程序将在PostgreSQL之前响应jdbc:// postgresql连接字符串。连接到PostgreSQL数据库时,这会导致JDBC错误。
我正在指定驱动程序名称' org.postgresql.Driver'作为我的pom.xml中数据源的驱动程序,但我不确定spring JDBC模板是如何选择驱动程序的(除非它拿起第一个处理程序)。
其他人遇到过这类问题吗?
答案 0 :(得分:14)
另一个解决方案是添加" OpenSourceSubProtocolOverride = true"到常规PostgreSQL连接的JDBC连接字符串。
示例:
jdbc:postgresql://localhost:5432/postgres?OpenSourceSubProtocolOverride=true
答案 1 :(得分:4)
这是因为redshift驱动程序注册为能够同时处理jdbc:postgresql
和jdbc: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