2008-11-14 2 views
17

Мне нужно проверить соединение JDBC с базой данных. Код Java, чтобы сделать это должно быть так же просто, как:Как использовать драйвер JDBC из произвольного местоположения

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

менеджер драйверов будет искать подходящий драйвер для данного соединения URL. Однако мне нужно иметь возможность загружать драйвер JDBC (jar) во время выполнения. I.e У меня нет драйвера JDBC на пути к классам приложения java, который выполняет фрагмент кода выше.

Так что я могу загрузить драйвер с помощью этого кода, например:

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

Но тогда менеджер водитель все равно не будет забрать его, как я не могу сказать ему, какой загрузчик классов использовать. Я попытался установить загрузчик классов контекста текущего потока, и он все еще не работает.

У кого-нибудь есть идеи по наилучшему способу достижения этого?

+0

Есть ли веская причина, почему у вас нет драйвера на пути к классам? – 2008-11-14 00:16:10

ответ

17

Из статьи Pick your JDBC driver at runtime; Я просто отправлю код здесь для справки.

Идея состоит в том, чтобы обмануть диспетчера драйверов, считая, что драйвер был загружен из системного загрузчика классов. Для этого мы используем этот класс:

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(); 
    } 
} 

Таким образом, водитель регистрации имеет тип DelegatingDriver, который загружается с системой загрузчиком классов. Теперь вам просто нужно загрузить драйвер, который вы действительно хотите использовать, используя любой загрузчик классов, который вы хотите. Например:

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

Проблема заключается в том DriverManager выполняет «задачи, используя загрузчик класса экземпляра вызывающей функции». См. Руководство 6-3 от Secure Coding Guidelines for the Java Programming Language, version 2.0. В этом случае загрузчик системного класса никоим образом не является особенным.

Просто для пинок, я написал blog entry по этому вопросу некоторое время назад. Мое решение, хотя и более сложное, чем Nick Sayer's solution, более полно и даже работает от ненадежного кода. Также примечание URLClassLoader.newInstance является предпочтительным по сравнению с new URLClassLoader.

Смежные вопросы