[英]Redshift and Postgres JDBC driver both intercept jdbc://postgresql connection string
我有一個不太確定如何解決的問題:我有一個 Web 應用程序(打包為 war)並且客戶端可以配置他們希望指向的數據庫。 我們支持 PostgreSQL 和 Redshift(以及其他)。 JDBC4 驅動是自動加載的,很好。 這是問題所在:
看起來 Redshift JDBC 驅動程序會在 PostgreSQL 之前響應 jdbc://postgresql 連接字符串。 這會在連接到 PostgreSQL 數據庫時導致 JDBC 錯誤。
我在 pom.xml 中指定驅動程序名稱 'org.postgresql.Driver' 作為數據源的驅動程序,但我不確定 spring JDBC 模板如何選擇驅動程序(除非它選擇第一個處理程序)。
還有其他人遇到這種問題嗎?
另一種解決方案是將“OpenSourceSubProtocolOverride=true”添加到常規 PostgreSQL 連接的 JDBC 連接字符串。
例子:
jdbc:postgresql://localhost:5432/postgres?OpenSourceSubProtocolOverride=true
這是因為 redshift 驅動程序注冊為能夠處理jdbc:postgresql
和jdbc:redshift
URL 前綴。
當 Postgres 和 Redshift 驅動程序從它們的 jars 加載時,它們每個都向 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;
}
}
}
太糟糕了,我在解決問題之前沒有看到其他答案,但我通過執行此操作覆蓋 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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.