2015-08-11 14 views
5

Ho un problema che non sono abbastanza sicuro di come risolvere: ho un'applicazione web (pacchettizzata come una guerra) e i client possono configurare quale database desidero indicare. Supportiamo sia PostgreSQL che Redshift (così come altri). I driver JDBC4 sono caricati automaticamente, il che è buono. Ecco il problema:JDBC driver Redshift e Postgres intercettano jdbc: // stringa di connessione postgresql

Sembra che il driver JDBC di Redshift risponderà alla stringa di connessione jdbc: // postgresql prima di PostgreSQL. Ciò causa errori JDBC durante la connessione a un database PostgreSQL.

Sto specificando il nome del driver 'org.postgresql.Driver' come driver per l'origine dati nel mio pom.xml, ma non sono sicuro di come i modelli JDBC primaverili scelgano il driver (a meno che non prelevi il primo gestore).

Qualcun altro si imbatte in questo tipo di problema?

risposta

2

Questo perché il driver redshift si registra come in grado di gestire sia il prefisso URL jdbc:postgresql e jdbc:redshift.

Quando i driver Postgre & Redshift vengono caricati dai loro barattoli, ciascuno si registra con DriverManger.

La logica implementata in DriverMananger.getDriver() e DriverManager.getConnection() consiste nel fare un ciclo di ciascun driver e fermarsi una volta che un driver indica che è in grado di gestire l'URL specificato.

Se il driver Postgres si registra per primo, tutto funziona correttamente poiché il driver Postgres tenta solo di gestire jdbc:postgresql. Se il driver Redshift riesce a registrare prima, il driver Postgres non verrà mai utilizzato.

L'unico modo che ho capito per risolvere questo è quello di aggiungere:

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; 
     } 
    } 
} 
+0

Stiamo utilizzando i modelli primavera JDBC, c'è un modo per specificare per un DataSource il conducente che deve essere utilizzato? Pensavo di aver visto qualcosa come setDriver() su Driver manager, ma sono un po 'un noob di primavera ... –

+0

Non ho familiarità con la primavera, quindi non sono sicuro. Se la primavera usa solo il DriverManager dietro le quinte, penso che riordinare i driver dovrebbe fare il trucco. –

5

Un'altra soluzione potrebbe essere quella di aggiungere "OpenSourceSubProtocolOverride = true" per stringa di connessione JDBC per le connessioni PostgreSQL regolari.

Esempio:

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

risolto per me aggiungendo agli URL esistenti i PG db. – jhnclvr

Problemi correlati