Проблемы с Hibernate и часовой пояс в mysql [дубликат]

Предположим, что у вас есть следующий код

fruits = ("apples", "bananas", "loganberries")

def eat(food=fruits):
    ...

Когда я вижу декларацию о еде, наименее удивительной является мысль, что если первый параметр не указан, он будет равен tuple ("apples", "bananas", "loganberries")

Однако, предположим позже в коде, я делаю что-то вроде

def some_random_function():
    global fruits
    fruits = ("blueberries", "mangos")

, тогда, если параметры по умолчанию были связаны с выполнением функции, а не с объявлением функции, тогда я бы удивляйтесь (очень плохо), чтобы обнаружить, что фрукты были изменены. Это было бы более удивительно ИМО, чем обнаружение того, что ваша функция foo, указанная выше, мутировала список.

Реальная проблема заключается в изменяемых переменных, и все языки имеют определенную проблему. Возникает вопрос: предположим, что в Java у меня есть следующий код:

StringBuffer s = new StringBuffer("Hello World!");
Map<StringBuffer,Integer> counts = new HashMap<StringBuffer,Integer>();
counts.put(s, 5);
s.append("!!!!");
System.out.println( counts.get(s) );  // does this work?

Теперь, использует ли моя карта значение ключа StringBuffer, когда оно было помещено на карту, или оно хранит ключ по ссылке? В любом случае, кто-то удивлен; либо человек, который попытался получить объект из Map, используя значение, идентичное тому, с которым он положил его, или человек, который, похоже, не может получить свой объект, даже если ключ, который они используют, буквально тот же объект, который использовался для размещения его на карте (на самом деле Python не позволяет использовать его изменяемые встроенные типы данных в качестве словарных клавиш).

Ваш пример хороший случая, когда новички Python будут удивлены и укушены. Но я бы сказал, что если бы мы «исправили» это, тогда это создало бы другую ситуацию, в которой они были бы укушены, и это было бы еще менее интуитивным. Более того, это всегда имеет место при работе с изменяемыми переменными; вы всегда сталкиваетесь с ситуациями, когда кто-то может интуитивно ожидать одно или наоборот поведения в зависимости от того, какой код они пишут.

Мне лично нравится текущий подход Python: аргументы функции по умолчанию оцениваются, когда функция определена, и что объект всегда является значением по умолчанию. Я предполагаю, что они могут использовать специальный случай с пустым списком, но такой специальный корпус вызовет еще большее удивление, не говоря уже о несовместимости в обратном направлении.

22
задан Xilang 30 September 2011 в 05:29
поделиться

1 ответ

useTimezone - это более раннее решение. Команда MySQL переписала код setTimestamp / getTimestamp довольно недавно, но она будет включена, только если вы установили параметр соединения useLegacyDatetimeCode = false, и вы используете последнюю версию соединителя JDBC mysql. Например:

String url =
 "jdbc:mysql://localhost/mydb?useLegacyDatetimeCode=false

Если вы загрузите исходный код mysql-коннектора и посмотрите на setTimestamp, очень легко увидеть, что происходит:

Если использовать устаревший код времени даты = false, newSetTimestampInternal (...). Затем, если Календарь, переданный в newSetTimestampInternal, равен NULL, ваш объект даты форматируется в часовом поясе базы данных:

this.tsdf = new SimpleDateFormat("''yyyy-MM-dd HH:mm:ss", Locale.US);
this.tsdf.setTimeZone(this.connection.getServerTimezoneTZ());
timestampString = this.tsdf.format(x);

Очень важно, чтобы Calendar был нулевым - поэтому убедитесь, что вы используете:

setTimestamp(int,Timestamp).

... NOT setTimestamp (int, Timestamp, Calendar).

Теперь должно быть очевидно, как это работает. Если вы построите дату: 5 января 2011 г. 3:00 в Америке / Los_Angeles (или любой другой часовой пояс, который вы хотите), используя java.util.Calendar и call setTimestamp (1, myDate), тогда он примет вашу дату, используйте SimpleDateFormat для его форматирования в часовом поясе базы данных. Итак, если ваша БД находится в Америке / New_York, она построит String '2011-01-05 6:00:00', чтобы вставить (поскольку NY опережает LA на 3 часа).

To получить дату, использовать getTimestamp (int) (без календаря).

Примечание: часовой пояс веб-сервера совершенно неактуален! Если вы не установили для useLegacyDatetimecode значение false, временной интервал веб-сервера используется для форматирования - добавление большого количества путаницы.


Примечание:

Возможно, MySQL мой жалуется, что серверный часовой пояс неоднозначен. Например, если ваша база данных настроена на использование EST, в Java может быть несколько возможных часовых поясов EST, поэтому вы можете пояснить это для mysql-коннектора, указав точно, что такое часовой пояс базы данных:

String url =
 "jdbc:mysql://localhost/mydb?useLegacyDatetimeCode=false&serverTimezone=America/New_York";

Вам нужно только сделать это, если он жалуется.

52
ответ дан nogridbag 21 August 2018 в 10:38
поделиться
  • 1
    Благодарим вас за предложение useLegacyDatetimeCode! Примечание. Это также решило мои проблемы, связанные с Joda Time (также с помощью надстройки hibernate). – Pete 11 December 2012 в 00:19
  • 2
    Таким образом, с serverTimezone и useLegacyDatetimeCode, добавленным к моей строке подключения, я могу отправить Timestmp, и он будет правильно записан в столбце DateTime, так как это время UTC. Я вижу это на моей консоли MySQL как таковой. Когда я делаю SELECT через JDBC и пытаюсь извлечь данные, он все равно автоматически преобразует его в слой JDBC. Я пробовал getObject () и geTimestmp (как без, так и с календарным объектом UTC), и он продолжает возвращаться в локальное время. – djsumdog 4 May 2014 в 15:31
  • 3
    Оказывается, это была настройка, которая мне нужна для решения производственной проблемы. Локально мы не могли воспроизвести его. Но попытка этого в драйвере на производстве устранила срыв, который мы наблюдали после 10-30 секунд обработки. – Robert Casto 21 March 2016 в 18:00
  • 4
    @djsumdog - информация о часовом поясе не сохраняется в классе Timestamp. Поэтому, когда вы печатаете объект даты в консоли, он будет отформатирован в часовом поясе JVM. – nogridbag 4 May 2016 в 18:58
  • 5
    не исправить ошибку на 6.0.2 – James111 9 June 2016 в 08:05
Другие вопросы по тегам:

Похожие вопросы: