Драйвер JDBC MySQL 5.1.33 - проблема с часовым поясом

184

Некоторая предыстория:

У меня есть Java 1.6 webapp, работающий на Tomcat 7. База данных - это MySQL 5.5. Раньше я использовал драйвер Mysql JDBC 5.1.23 для подключения к БД. Все сработало. Недавно я обновился до драйвера Mysql JDBC 5.1.33. После обновления Tomcat выбросит эту ошибку при запуске приложения.

WARNING: Unexpected exception resolving reference
java.sql.SQLException: The server timezone value 'UTC' is unrecognized or represents more than one timezone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc timezone value if you want to utilize timezone support.

Почему это происходит?

  • 0
    Как выглядит ваш JDBC URL?
  • 0
    Проверьте мой ответ stackoverflow.com/a/44720416/4592448 . Думаю лучший ответ)
Теги:
tomcat
timezone
jdbc

17 ответов

327
Лучший ответ

По-видимому, чтобы получить версию 5.1.33 драйвера JDBC MySQL для работы с часовым поясом UTC, нужно явно указать serverTimezone в строке подключения.

jdbc:mysql://localhost/db?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
  • 2
    Согласно документам useJDBCCompliantTimezoneShift не имеет никакого эффекта при использовании useLegacyDatetimeCode = false. Поэтому там не нужно ...
  • 11
    Это решает мою ошибку. Дополнительное примечание, выберите & с & amp; в файле persistence.xml: <property name = "javax.persistence.jdbc.url" value = "jdbc: mysql: // localhost / test? useUnicode = true & amp; useJDBCCompliantTimezoneShift = true & amp; useLegacyDatetimeCode = false & amp; serverTimezone = UTC>
Показать ещё 6 комментариев
44

Если вы используете Maven, вы можете просто установить другую версию соединителя MySQL (у меня была такая же ошибка, поэтому я изменил ее с 6.0.2 на 5.1.39) в pom.xml:

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.39</version>
</dependency>

Как сообщается в других ответах, эта проблема была исправлена ​​в версиях 6.0.3 или выше, поэтому вы можете использовать обновленную версию:

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>6.0.3</version>
</dependency>

Maven автоматически перестроит ваш проект после сохранения файла pom.xml.

  • 14
    Спасибо, решение работает. Они также не исправили это в 6.0.3.
  • 0
    Всегда пожалуйста @Джанет. Надеюсь, мы сможем поддерживать связь, чтобы обновить это решение, когда оно также изменится.
Показать ещё 5 комментариев
29

Я решил эту проблему, настроив MySQL.

SET GLOBAL time_zone = '+3:00';

  • 4
    если вы используете часовой пояс MSK, это +3, тогда вы можете использовать следующий адрес в качестве адреса БД: jdbc:mysql://localhost/db?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Europe/Moscow . Похоже, MySQL-разъем не понимает короткие имена часовых поясов.
  • 1
    Что вы делаете, когда летнее время меняет время?
Показать ещё 1 комментарий
27

Это ошибка в mysql-connector-java от версии 5.1.33 до 5.1.37. Я сообщил об этом здесь: http://bugs.mysql.com/bug.php?id=79343

Отредактировано: Это было исправлено из mysql-connector-java 5.1.39

Это была опечатка в классе TimeUtil в методе loadTimeZoneMappings, которая вызывает поиск NPE файла /com/mysql/jdbc/TimeZoneMapping.properties. Если вы посмотрите на код, файл должен находиться в загрузчике классов TimeUtil, а не TimeZone:

TimeUtil.class.getResourceAsStream(TIME_ZONE_MAPPINGS_RESOURCE);

Параметр useLegacyDatetimeCode позволяет автоматически корректировать разницу между часовыми поясами клиента и сервера при использовании дат. Таким образом, это помогает вам точно не указывать часовые пояса в каждой части. Хотя использование параметра serverTimeZone является обходным решением, а между тем патч выпущен, вы можете попробовать лучше исправить код самостоятельно, как я.

  • Если это автономное приложение, попробуйте просто добавить скорректированный класс com/mysql/jdbc/TimeUtil для вашего кода и будьте осторожны с порядком загрузки контейнера. Это может помочь: https://owenou.com/2010/07/20/patching-with-class-shadowing-and-maven.html

  • Если это веб-приложение, более простым решением является создание собственного mysql-connector-java-5.1.37-patched.jar, подставляя .class напрямую в оригинальную банку.

  • 0
    Милый, спасибо за сообщение об этом. Рад, что кто-то смог зафиксировать ошибку. Вы знаете, когда будет выпущено исправление?
  • 0
    Решение, которое вы предлагаете, великолепно, но я думаю, что изменение источника драйвера и управление зависимостями Maven, вероятно, слишком раздражает для большинства людей.
Показать ещё 6 комментариев
25

Строка подключения должна быть установлена ​​следующим образом:

jdbc:mysql://localhost/db?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC

Если вы определяете соединение в файле xml (например, persistence.xml, standalone-full.xml и т.д.), вместо & вы должны использовать &amp; или использовать блок CDATA.

  • 1
    Это не правильно. Точка useLegacyDatetimeCode = false не обязывает указывать serverTimezone, поэтому клиент исправляет различия часовых поясов.
  • 0
    добавление & amp; работал на меня
17

Я решил поставить ниже строку подключения в URL-адрес

jdbc:mysql://localhost:3306/db?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
12

У меня такая же проблема, и я решил, что добавляет только "? ServerTimezone = UTC" в мое строковое соединение.

#

синошь моя проблема:

java.sql.SQLException: значение часового пояса сервера "CEST" непризнано или представляет собой более одного часового пояса. Вы должны настроить драйвер сервера или JDBC (через свойство конфигурации serverTimezone), чтобы использовать более определенное значение часового пояса, если вы хотите использовать поддержку часового пояса.

my dbDriver = com.mysql.jdbc.Driver

my jar = mysql-connector-java-8.0.12.jar

my java = 1.8

my tomcat = Apache Tomcat Version 8.5.32

my MySql server = MySql ver.8.0.12 
6
  • Я добавил в конфигурационный файл mysql в разделе [mysqld]

    default_time_zone='+03:00'
    
  • И перезагрузите сервер mysql:

    sudo service mysql restart
    

Где +03: 00 мой часовой пояс UTC.

Путь к файлу конфигурации на моем os ubuntu 16.04:

/etc/mysql/mysql.conf.d/mysqld.cnf

ПРЕДУПРЕЖДЕНИЕ: ЕСЛИ ВАША ВРЕМЕННАЯ ЗОНА ИМЕЕТ ЛЕТО И ЗИМНЕЕ ВРЕМЯ. ВЫ ДОЛЖНЫ ИЗМЕНИТЬ UTC В КОНФИГУКЕ, ЧТО ВРЕМЯ ИЗМЕНЕНИЯ. ДВАЖДЫ В ГОД (ПОСЛЕДУЮЩАЯ) ИЛИ УСТАНОВИТЕ КРОНТАБ С СУДО.

Соединение с моим url jdbc:

"jdbc:mysql://localhost/java"
  • 0
    Необходимость перезапуска Mysql практически не запускается практически во всех случаях производственного использования. Это становится еще более серьезной проблемой, когда задействованы репликации.
  • 0
    @bluecollarcoder Требуется добавить только в разделе [mysqld]. Или добавьте раздел [mysqld], если у него нет раздела. Пример моего конфига pastebin.com/j4F7t2KS
Показать ещё 2 комментария
5

После прочтения нескольких постов на эту тему, тестирования различных конфигураций и на основе некоторых выводов из этой ветки ошибок MySQL я понял следующее:

  • часовой пояс сервера важен, в частности, для преобразования дат, хранящихся в базе данных, в часовой пояс сервера приложений. Есть и другие последствия, но это самое заметное
  • GMT x UTC системы часовых поясов. GMT был задуман в конце 19-го века и может быть переключен между стандартным и летним временем. это свойство может привести к ситуации, когда сервер базы данных перейдет на летнее время, а приложение не заметит этого (возможно, существуют другие сложности, но я не стал исследовать дальше). UTC (по времени Португалии, а не по Гринвичу по Гринвичу) не изменяется во времени, поэтому является более стабильным
  • Определение serverTimeZone было введено в соединителях mysql jdbc версии 5.1. до версии 8 его можно было игнорировать с помощью useLegacyDatetimeCode=true, что в сочетании с useJDBCCompliantTimezoneShift=true заставляло бы приложение получать часовой пояс базы данных при каждом подключении. В этом режиме часовые пояса GMT, такие как "Британское летнее время", будут преобразованы во внутренний формат Java/JDBC. Новые часовые пояса могут быть определены в файле .properties, таком как этот
  • Начиная с версии 8 драйвера jdbc, автоматическое сопоставление времени (useJDBCCompliantTimezoneShift) и устаревший формат времени (useLegacyDatetimeCode) были удалены (см. Журнал изменений коннектора mysql jdbc). поэтому установка этих двух параметров не имеет никакого эффекта, поскольку они полностью игнорируются (новое значение по умолчанию - useLegacyDateTimeCode=false)
  • Таким образом, настройка serverTimezone стала обязательной, если какой-либо из часовых поясов (серверы приложений/баз данных) не в формате "UTC + xx" или "GMT + xx"
  • Установка времени сервера как UTC не влияет (например, с помощью jdbc:mysql://localhost:3306/myschema?serverTimezone=UTC, даже если ваши серверы приложений/баз данных не находятся в этом часовом поясе. Это важно для подключения приложения Синхронизация строки + базы данных с одним и тем же часовым поясом. Другими словами, просто установка serverTimezone = UTC с другим часовым поясом на сервере базы данных сместит любые даты, извлеченные из базы данных.
  • Часовой пояс MySQL по умолчанию можно установить в UTC + 0 с файлами my.ini или my.cnf (соответственно windows/linux), добавив строку default-time-zone='+00:00' (подробности в https://stackoverflow.com/questions/19903610/how-to-set-permanent-default-timezone-in-mysql-server)
  • Базы данных, настроенные в AWS (веб-сервисы Amazon), автоматически получают время по умолчанию UTC + 0 (см. Страницу справки AWS здесь)
4

Все, что нам нужно, чтобы исправить проблему с serverTimezone:

String url = "jdbc:mysql://localhost:3306/db?serverTimezone=" + TimeZone.getDefault().getID()
  • 0
    Спасибо, добрый сэр
4

Я использую mysql-connector-java-8.0.13 и имею ту же проблему. Я создал свою базу данных в консоли командной строки и решил эту проблему с помощью решения @Dimitry Rud в командной строке:

SET GLOBAL time_zone = '-6:00';

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

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

1

У меня также была такая же проблема в LibreOffice Base. Поэтому я просто указал в строке подключения не "летнее время".
Изображение 898

Я пробовал без "& serverTimezone = MST", но это тоже не удалось.

Я также попытался "& serverTimezone = MDT", и это не удалось, поэтому по какой-то причине ему не нравится переход на летнее время!

1

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

0

Из mysql workbench запустите следующие операторы sql:

  1. SET @@global.time_zone = '+00: 00';
  2. SET @@session.time_zone = '+00: 00';

с помощью следующих операторов sql проверьте, были ли установлены значения:

SELECT @@global.time_zone, @@session.time_zone;

0

Решение @Ingvar сработало.

String url = "jdbc:mysql://localhost:330/db?serverTimezone="+TimeZone.getDefault().getID()
  • 0
    это должен быть комментарий или что-то подобное, а не отдельный ответ
0

Согласитесь с ответом @bluecollarcoder, но лучше использовать TimeZone.getDefault().getID(); в конце строки подключения:

"jdbc:mysql://localhost/db?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=" + TimeZone.getDefault().getID();  

В этом случае параметр Timezone автоматически обновляется в зависимости от часового пояса локального компьютера.

-6
package pack1;

import java.sql.Connection;
import java.sql.DriverManager;
import javax.swing.JOptionPane;

public class sqliteConnection {
    Connection conn=null;

    public static Connection dbConnector() {
        try {Class.forName("com.mysql.jdbc.Driver");

        Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306", "root", "");
        JOptionPane.showMessageDialog(null, "connection is succesful");
        return conn;

        } catch(Exception e) {
            JOptionPane.showMessageDialog(null, e);
            return null;

        ////you need also to execute this in database ===> SET GLOBAL time_zone = '+3:00';
        }
    }
}
  • 1
    Это не имеет ничего общего с заданным вопросом.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню