Почему поиск DriverManager.getConnection() не работает в GroovyConsole?

Следующий скрипт Groovy правильно работает из командной строки. (Я успешно получаю соединение.)

// ---- jdbc_test.groovy
import java.sql.*
Class.forName("com.mysql.jdbc.Driver")
def con = DriverManager.getConnection(
    "jdbc:mysql://localhost:3306/test",
    "root",
    "password")
println con

> groovy -cp lib\mysql-connector-java-5.1.25-bin.jar script\jdbc_test.groovy
com.mysql.jdbc.JDBC4Connection@6025e1b6

Но если тот же скрипт загрузить в GroovyConsole (2.4.3) и запустить - после добавления mysql-connector-java-5.1.25-bin.jar с помощью 'Script' | «Добавить банку (ы) в ClassPath» - не удается:

java.sql.SQLException: No suitable driver found for jdbc:mysql://localhost:3306/test
at java_sql_DriverManager$getConnection.call(Unknown Source)
at jdbc_test.run(jdbc_test.groovy:3)

Все остальные пакеты или классы, которые я добавлял в путь к классам в GroovyConsole и с которыми экспериментировал, работали. Есть ли какое-то неожиданное взаимодействие между загрузкой классов Groovy и тем, как работает DriverManager?

Есть ли способ обойти это? Я пытаюсь использовать GroovyConsole для интерактивного тестирования кода JDBC (библиотеки функций, каждая из которых принимает Connection в качестве первого аргумента).

ОБНОВЛЕНИЕ: часть Class.forName() работает нормально. Если я «Сценарий» | «Очистить контекст сценария» и повторно запустить сценарий в GroovyConsole, вместо этого я получаю:

java.lang.ClassNotFoundException: com.mysql.jdbc.Driver

Если я снова добавлю mysql-connector-java-5.1.25-bin.jar, я вернусь к получению:

java.sql.SQLException: No suitable driver found for jdbc:mysql://localhost:3306/test

person Paul    schedule 12.06.2015    source источник


Ответы (1)


Решение. Драйвер должен находиться в пути к классам.

Причина: Если вы посмотрите на класс DriverManager, вы обнаружите такой код: Class.forName(driver.getClass().getName(), true, classLoader);. Это нужно, чтобы проверить, доступен ли драйвер из вашего контекста загрузчика классов. И этот контекст определяется путем возврата к классу, вызывающему DriverManager. Этот код написан для Java, поэтому предполагается, что определенное количество кадров в стеке вызовов будет возвращено. Поскольку Groovy не выполняет прямых вызовов (если только вы не используете @CompileStatic), это число неверно и обычно приводит к выбору базового класса Groovy, что приводит к выбору основного загрузчика Groovy... в прошлом это часто было даже Загрузчик классов системы JDK из-за отражения. Таким образом, хотя драйвер загружен и зарегистрирован, он недоступен для вас.

Примечание: с jdbc4 драйвер должен зарегистрироваться, просто находясь в пути к классам

person blackdrag    schedule 13.06.2015
comment
Спасибо. Это хорошо объясняет. Кажется, что самый простой способ сделать файл jar драйвера доступным для GroovyConsole — поместить его в {user.home}/.groovy/lib. Это одно из мест, включенных в файл Groovy conf/groovy-starter.conf. - person Paul; 14.06.2015
comment
Спасибо за этот ответ! Вместо того, чтобы вставлять jar-файл драйвера в путь к классам, я закончил прокси-вызовы DriverManager через класс, написанный на Java, который, похоже, тоже работает нормально. - person David; 12.08.2016