почему DriverManager.getConnection не использует метод «acceptptsURL» из Driver.class - PullRequest
1 голос
/ 31 октября 2019

Я читаю код JDBC. В DriverManager.getConnection я обнаружил, что он работает следующим образом: он пытается подключить каждый известный ему драйвер до его успешного завершения.

Вот код:

        for(DriverInfo aDriver : registeredDrivers) {
            // If the caller does not have permission to load the driver then
            // skip it.
            if(isDriverAllowed(aDriver.driver, callerCL)) {
                try {
                    println("    trying " + aDriver.driver.getClass().getName());
                    Connection con = aDriver.driver.connect(url, info);
                    if (con != null) {
                        // Success!
                        println("getConnection returning " + aDriver.driver.getClass().getName());
                        return (con);
                    }
                } catch (SQLException ex) {
                    if (reason == null) {
                        reason = ex;
                    }
                }

            } else {
                println("    skipping: " + aDriver.getClass().getName());
            }

        }

Но есть метод "acceptsURL "из интерфейса Driver:

    boolean acceptsURL(String url) throws SQLException;

Итак, мой вопрос, почему DriverManager не вызывает этот метод до того, как он установит реальное соединение для фильтрации несвязанных драйверов?

Или с кодом, может быть, это лучше?

        for(DriverInfo aDriver : registeredDrivers) {
            // If the caller does not have permission to load the driver then
            // skip it.
            if(isDriverAllowed(aDriver.driver, callerCL) && aDriver.driver.acceptsURL(url)) {
                try {
                    println("    trying " + aDriver.driver.getClass().getName());
                    Connection con = aDriver.driver.connect(url, info);
                    if (con != null) {
                        // Success!
                        println("getConnection returning " + aDriver.driver.getClass().getName());
                        return (con);
                    }
                } catch (SQLException ex) {
                    if (reason == null) {
                        reason = ex;
                    }
                }

            } else {
                println("    skipping: " + aDriver.getClass().getName());
            }

        }

1 Ответ

3 голосов
/ 31 октября 2019

Реализованная реализация DriverManager (OpenJDK) не использует acceptsUrl. Это не обязательно означает, что есть нет DriverManager реализаций, использующих его. На самом деле, насколько я помню, более ранние реализации Sun Java вызывали acceptsURL. Основная причина, по которой он не вызывается, заключается в том, что спецификация JDBC требует DriverManager для вызова connect для каждого зарегистрированного драйвера в любом случае. См. Ниже.

Ничто в спецификации или документации API не говорит о том, что DriverManager должен использовать acceptsURL. Спецификация JDBC 4.3 только об этом говорит (раздел 9.2 Интерфейс Driver ):

Класс DriverManager вызывает Driver методы, когдаон хочет взаимодействовать с зарегистрированным водителем. Интерфейс Driver также включает метод acceptsURL. DriverManager может использовать этот метод, чтобы определить, какой из зарегистрированных драйверов он должен использовать для данного URL.

(выделено мной)

Обратите внимание наиспользование слова может вместо необходимо или будет .

В следующем абзаце говорится:

КогдаDriverManager пытается установить соединение, он вызывает метод connect этого драйвера и передает драйверу URL. Если реализация Driver распознает URL-адрес, она вернет объект Connection или выдаст SQLException, если невозможно подключить соединение [sic] к базе данных. Если реализация Driver не понимает URL, она вернет null.

. Кроме того, в разделе 9.4 DriverManager class написано:

  • getConnection - метод, который клиент JDBC вызывает для установления соединения. Вызов включает в себя URL JDBC, который DriverManager передает каждому драйверу в своем списке, пока не найдет тот, чей метод Driver.connect распознает URL . Этот драйвер возвращает объект Connection в DriverManager, который, в свою очередь, передает его приложению.

(выделение мое)

Как я это прочитал,вызов Driver.connect для каждого драйвера в любом случае требуется, поэтому для реализации нет смысла вызывать acceptsURL.

Теперь, что касается того, почему спецификация JDBC написана таким образом, я не знаю,и я сам являюсь членом экспертной группы JSR-221 (JDBC 4). Когда я присоединился к экспертной группе, реализация (и спецификация) были уже такими, поэтому я не знаю ее истории. Однако я не уверен, что вы получите лучший ответ, чем приведенный выше, неудовлетворительный ответ (это так, потому что в спецификации так сказано).

Однако, если бы мне пришлось угадывать, это, вероятно, связано стот факт, что для некоторых водителей определение того, могут ли они принять URL, может быть относительно сложным или дорогим. В этом случае лучше просто попытаться подключиться, потому что для драйвера, отклоняющего URL-адрес, стоимость равна (или должна быть) такой же, как простой вызов acceptsURL, тогда как для драйвера, который фактически примет URL-адрес, стоимость будетударить дважды, если DriverManager сначала вызовет acceptsURL, а затем connect.

Это не означает, что метод acceptsURL совершенно не имеет значения. Некоторые приложения (например, некоторые инструменты запросов или инструменты отчетов) используют его, чтобы определить, какие драйверы будут обрабатывать определенный URL, поэтому они могут запросить реализацию Driver для их поддерживаемых свойств соединения (Driver.getPropertyInfo​) чтобы они могли заполнить там мастер соединений доступными свойствами. Другие программы могут использовать его для получения информации, такой как его версия (Driver.getMajorVersion, Driver.getMinorVersion), родительский логгер (Driver.getParentLogger) или соответствие JDBC (Driver.jdbcCompliant).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...