Java: Как сохранить дату в MySQL без преобразования часового пояса? - PullRequest
0 голосов
/ 18 февраля 2020

Я сохраняю день рождения с Java8 + MyBatis + MySQL5.7. Мой код выглядит так:

// 'birthday' is a DATE column
@Insert("insert into MyTable (id, birthday) values (#{id"}, #{date})")
void saveDate(int id, LocalDate date);

@Select("select birthday from MyTable where id=#{id"}")
LocalDate loadDate(@Param("id") int id);

И код для сохранения и загрузки даты.

final int id = 1;
final LocalDate date = LocalDate.of(2020, 1, 3);

repo.saveDate(id, date);
LocalDate dateFromDB = repo.loadDate(id);

System.out.println(date);        // 2020-1-3
System.out.println(dateFromDB);  // 2020-1-2

Я заметил, что значение "dateFromDB" всегда за один день до " свидание". Я думаю, что это вызвано преобразованием часового пояса. Так как мое приложение на UTC + 8, а БД использует UT C. Используя DATETIME вместо DATE, я вижу, что дата '2020-1-3' сохраняется как '2020-1-2 16: 0: 0'.

Итак, вопрос в том, как избежать преобразования часового пояса при сохранении даты, например, дня рождения?

----------------- Обновлено 2020-02-20 ------- -----------------------------

Пока я нашел 4 способа сделать это:

  1. Добавьте параметр noTzConversionForDateType=true, чтобы избежать преобразования только для типа даты. Это лучший способ, но он применим только к версии 5.1 . Я действительно не понимаю, почему он удален из версии 8.0 ... ( document )
  2. Добавьте параметр serverTimezone=GMT%2B8, используя часовой пояс клиента (UTC + 8) в качестве часового пояса сервера. Преобразование все еще происходит, но это ничего не меняет. Проблема в том, что TIMESTAMP столбцы также будут затронуты.
  3. Добавьте параметр -Duser.timezone=UTC в JVM. Проблема похожа на # 2.
  4. Отправьте LocalDate значение как String. Обновите функцию saveDate, как показано ниже (измените только тип с LocalDate на String):
@Insert("insert into MyTable (id, birthday) values (#{id"}, #{date})")
void saveDate(int id, String date);

Затем преобразуйте дату в String перед вызовом saveDate:

String dateString = date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
repo.saveDate(id, dateString);

Обратите внимание, что тип данных в БД по-прежнему DATE. Преимущество этого способа заключается в том, что будет затронут только столбец birthday. Проблема в том, что код не элегантный и может привести к проблемам с производительностью большого набора данных.

1 Ответ

0 голосов
/ 18 февраля 2020

Предполагается, что вы подключаетесь к MySQL, используя строку подключения, подобную приведенной ниже

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