Как использовать драйвер JDBC из произвольного места

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

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

Диспетчер драйверов будет искать соответствующий драйвер для данного URL-адреса подключения. Однако мне нужно иметь возможность загружать драйвер JDBC (jar) во время выполнения. То есть у меня нет драйвера 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();

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

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

Есть ли веская причина, по которой у вас нет драйвера в пути к классам?

Bill the Lizard 14.11.2008 03:16

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

SaM 14.11.2008 03:23

Тут я снова подумал как серверный разработчик ... :)

Bill the Lizard 14.11.2008 03:35
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
18
3
7 560
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Из статьи Выберите драйвер JDBC во время выполнения; Я просто размещу здесь код для справки.

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

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

Проблема в том, что DriverManager выполняет «задачи, используя экземпляр загрузчика классов непосредственного вызывающего абонента». См. Рекомендацию 6-3 Рекомендации по безопасному кодированию для Язык программирования Java, версия 2.0. Загрузчик системного класса в этом случае не является чем-то особенным.

Просто ради удовольствия, я недавно написал на эту тему запись в блоге. Мое решение, хотя и более сложное, чем Решение Ника Сэйера, более полное и даже работает с ненадежным кодом. Также обратите внимание, что URLClassLoader.newInstance предпочтительнее new URLClassLoader.

Другие вопросы по теме