Не найден подходящий драйвер при экспорте в JAR-файл?

#java #mysql #postgresql #jdbc #jar

#java #mysql #postgresql #jdbc #jar

Вопрос:

Я пытаюсь поместить свой проект в JAR, чтобы я мог запустить его как CLI. У меня есть два JDBC-коннектора, которые я использую, один для MySQL, другой для PostgreSQL. Оба находятся в одном каталоге и отлично работают, если я запускаю их в IDE. Когда я создаю JAR, соединитель MySQL по-прежнему работает нормально, однако при попытке установить соединение с PostgreSQL появляется следующая ошибка. Вывод терминала при запуске моего jarЧто меня действительно раздражает, так это то, что соединитель, похоже, включен в сборку jar. введите описание изображения здесьВ сборке перечислены как соединитель MySQL, так и соединитель PostgreSQL. Как я могу это исправить?

Ответ №1:

Проблема в том, что все драйверы JDBC, совместимые с JDBC-4, содержат файл /META-INF/services/java.sql.Driver , в котором перечислены java.sql.Driver реализации в файлах JAR. Это используется java.sql.DriverManager для загрузки доступных драйверов JDBC.

Процесс, который вы использовали для слияния, по-видимому, не объединяет разные файлы из драйверов в один файл, поэтому он содержит только содержимое одного из драйверов. В результате другой драйвер не загружается автоматически.

Возможные решения:

  1. Не объединяйте файлы JAR в один JAR, а вместо этого используйте Class-Path атрибут META-INF/MANIFEST.MF для указания используемых вами JAR-файлов и выполняйте свою программу с помощью java -jar your.jar
  2. Убедитесь META-INF/services/java.sql.Driver , что он правильно объединен (или, возможно, предоставьте свой собственный), в зависимости от того, как вы объединяете, может быть возможность настроить, какие файлы необходимо объединить
  3. Явно загрузите драйверы, используя Class.forName("com.mysql.cj.jdbc.Driver") и Class.forName("org.postgresql.Driver") (сделайте это для обоих, чтобы предотвратить проблемы, если порядок слияния файлов изменится, а другой файл выиграет)

Комментарии:

1. Спасибо. Class.forName(«org.postgresql.Driver»); на самом деле сделал трюк.

2. @ChristianKammerer Да, но, как я уже упоминал, я рекомендую загружать оба драйвера явно, на случай, если в будущем слиянии будет использоваться другой порядок и META-INF/services/java.sql.Driver победит версия PostgreSQL вместо версии MySQL.

3. Я не уверен, что полностью понимаю, но является ли это условием гонки, в которое загружается драйвер? Я вставил их оба для хорошей оценки, 😉

4. @ChristianKammerer Нет, речь идет о том, что вы создаете один JAR с содержимым нескольких JAR, и то, как вы объединяете эти JAR, не объединяет содержимое META-INF/services/java.sql.Driver файлов, которые существуют как в JAR MySQL Connector / J, так и в JAR PostgreSQL JDBC. Вместо этого он выбирает только содержимое одного файла (в данном случае из MySQL Connector / J). Итак, при DriverManager обнаружении доступных драйверов JDBC он находит один файл определения службы, в котором указан только драйвер MySQL Connector / J.