2008-11-14 23 views
17

Potrzebuję przetestować połączenie JDBC z bazą danych. Kod java powinien być tak prosty, jak:Jak używać sterownika JDBC z dowolnej lokalizacji

DriverManager.getConnection("jdbc connection URL", "username", "password"); 

Menedżer sterowników wyszuka odpowiedni sterownik dla danego adresu URL połączenia. Jednak muszę mieć możliwość załadowania sterownika JDBC (słoika) w czasie wykonywania. Nie mam sterownika JDBC w ścieżce klasy aplikacji java, która uruchamia fragment kodu powyżej.

Więc mogę załadować sterownika za pomocą tego kodu, na przykład:

URLClassLoader classLoader = new URLClassLoader(new URL[]{"jar URL"}, this.getClass().getClassLoader()); 
Driver driver = (Driver) Class.forName("jdbc driver class name", true, classLoader).newInstance(); 

Ale wówczas zarządca kierowca nadal nie będzie go podnieść, bo nie mogę tego powiedzieć, które classloader w użyciu. Próbowałem ustawić obiekt ładujący klasy kontekstowego bieżącego wątku i nadal nie działa.

Ktoś ma jakiś pomysł na najlepszy sposób, aby to osiągnąć?

+0

Czy istnieje dobry powód, dla którego nie masz sterownika w ścieżce klas? –

+0

Tak. Aplikacja może łączyć się z wieloma bazami danych. Ponadto nie mogę łączyć wszystkich sterowników ze względu na licencję. Co chcę osiągnąć, to proste okno dialogowe, w którym użytkownik może załadować słoik, gdy aplikacja jest uruchomiona. – SaM

+0

Tam znowu myślałem, że jestem programistą po stronie serwera ... :) –

Odpowiedz

17

Z artykułu Pick your JDBC driver at runtime; Zamierzam opublikować kod tutaj w celach informacyjnych.

Chodzi o to, aby przekonać menedżera sterownika do myślenia, że ​​sterownik został załadowany z programu ładującego klasy systemu. Aby to zrobić, używamy tej klasy:

public class DelegatingDriver implements Driver 
{ 
    private final Driver driver; 

    public DelegatingDriver(Driver driver) 
    { 
     if (driver == null) 
     { 
      throw new IllegalArgumentException("Driver must not be null."); 
     } 
     this.driver = driver; 
    } 

    public Connection connect(String url, Properties info) throws SQLException 
    { 
     return driver.connect(url, info); 
    } 

    public boolean acceptsURL(String url) throws SQLException 
    { 
     return driver.acceptsURL(url); 
    } 

    public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException 
    { 
     return driver.getPropertyInfo(url, info); 
    } 

    public int getMajorVersion() 
    { 
     return driver.getMajorVersion(); 
    } 

    public int getMinorVersion() 
    { 
     return driver.getMinorVersion(); 
    } 

    public boolean jdbcCompliant() 
    { 
     return driver.jdbcCompliant(); 
    } 
} 

ten sposób kierowca rejestracji jest typu DelegatingDriver który jest ładowany z classloader systemu. Teraz wystarczy załadować sterownik, którego naprawdę chcesz używać, używając dowolnego programu ładującego klasy. Na przykład:

URLClassLoader classLoader = new URLClassLoader(new URL[]{"path to my jdbc driver jar"}, this.getClass().getClassLoader()); 
Driver driver = (Driver) Class.forName("org.postgresql.Driver", true, classLoader).newInstance(); 
DriverManager.registerDriver(new DelegatingDriver(driver)); // register using the Delegating Driver 

DriverManager.getDriver("jdbc:postgresql://host/db"); // checks that the driver is found 
5

Problemem jest DriverManager „wykonuje zadania przy użyciu klasy instancji ładowarka bezpośrednim rozmówcy”. Zobacz wytyczne 6-3 z Secure Coding Guidelines for the Java Programming Language, version 2.0. Program ładujący klasy systemu nie jest w tym przypadku szczególny.

Tylko dla kopnięć, napisałem blog entry na ten temat jakiś czas temu. Moje rozwiązanie, choć bardziej skomplikowane niż Nick Sayer's solution, jest bardziej kompletne, a nawet działa z niezaufanego kodu. Warto również zauważyć, że preferowane jest ustawienie URLClassLoader.newInstance w porównaniu z new URLClassLoader.

Powiązane problemy