Я сохраняю день рождения с 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 способа сделать это:
- Добавьте параметр
noTzConversionForDateType=true
, чтобы избежать преобразования только для типа даты. Это лучший способ, но он применим только к версии 5.1 . Я действительно не понимаю, почему он удален из версии 8.0 ... ( document ) - Добавьте параметр
serverTimezone=GMT%2B8
, используя часовой пояс клиента (UTC + 8) в качестве часового пояса сервера. Преобразование все еще происходит, но это ничего не меняет. Проблема в том, что TIMESTAMP
столбцы также будут затронуты. - Добавьте параметр
-Duser.timezone=UTC
в JVM. Проблема похожа на # 2. - Отправьте
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
. Проблема в том, что код не элегантный и может привести к проблемам с производительностью большого набора данных.