Перед записью даты Java в столбец SQL TIMESTAMP, JDBC переводит дату из часового пояса JVM в часовой пояс сеанса базы данных? - PullRequest
25 голосов
/ 08 ноября 2010

Перед записью Java Дата в столбец SQL TIMESTAMP , JDBC переводит дату из часового пояса виртуальной машины Java в сеанс базы данных

Например, предположим, что часовой пояс виртуальной машины Java равен UTC , а часовой пояс сеанса базы данных - UTC-5 . Если Java-программа пытается сохранить 2000-01-01 00:00:00, передав ее PreparedStatement#setTimestamp(int, Timestamp), в соответствии со стандартом JDBC, будет ли база данных хранить TIMESTAMP '2000-01-01 00:00:00' или TIMESTAMP '1999-12-31 19:00:00'?

Ответы [ 4 ]

13 голосов
/ 08 ноября 2010

Нет, JDBC - это всего лишь API-интерфейс, позволяющий клиенту получить доступ к базе данных. Для хранения меток времени это должно зависеть от организации, которая пишет свои драйверы баз данных, соответствующие стандарту API JDBC.

Вот реализация реализации MySQL PreparedStatement. Кажется, они переводят часовой пояс Java JVM в часовой пояс MySQL (проверьте метод setTimestampInternal()).

7 голосов
/ 27 апреля 2011

Теперь мое требование - хранить значение в GMT / UTC независимо от часового пояса JVM Есть ли способ установить часовой пояс на лету, а затем сбросить его после завершения работы с JDBC?

Edit: Хорошо, я нашел способ обойти эту проблему. Сделал следующее

TimeZone default = TimeZone.getDefault();
try
{
  TimeZone.setDefault(TimeZone.getTimeZone("UTC"));

  //Do stuff with JDBC
}
finally
{
  TimeZone.setDefault(default);
}
2 голосов
/ 02 апреля 2013

Вы можете использовать перегруженный setTimestamp установщик, принимающий Calendar экземпляр, чтобы указать часовой пояс

Пример (если вы используете Joda datetime):

org.joda.time.DateTime sendDateUTC = new DateTime( DateTimeZone.UTC ).withMillis( millis );
statement.setTimestamp (1, sendDateUTC, sendDateUTC.toGregorianCalendar() );

Согласно javaDoc: Устанавливаетназначенный параметр для данного java.sql.Timestamp значения, используя данный Calendar объект.Драйвер использует объект Calendar для создания значения SQL TIMESTAMP, которое драйвер затем отправляет в базу данных.С объектом Calendar водитель может рассчитать временную метку с учетом пользовательского часового пояса.Если объект Calendar не указан, драйвер использует часовой пояс по умолчанию, то есть виртуальный компьютер, на котором запущено приложение.

void setTimestamp(int parameterIndex, java.sql.Timestamp x, Calendar cal)
    throws SQLException;
0 голосов
/ 22 мая 2014

Спекуляция тупая. Java.util.Date хранит миллисекунды с эпохи в системе отсчета GMT. Java.sql.Timestamp - это дата плюс наносекунды в той же системе отсчета. Все недешевые методы получения и установки используют систему отсчета GMT. Для любого вида здравомыслия часовой пояс по умолчанию для хранения метки времени должен быть GMT.

В многоуровневом приложении внешний интерфейс, драйвер и сервер базы данных могут находиться в разных часовых поясах. Некоторые из уровней могут быть в разных часовых поясах одновременно; например, если вы выполняете балансировку нагрузки через Интернет на континенте или если у вас есть мобильное приложение, подключающееся к центральному серверу. Облачная операционная среда была бы во многом таким же сценарием, когда вы не знаете, где будет работать драйвер JDBC, и не можете гарантировать, что он никогда не изменится.

Единственный известный мне способ достижения согласованности в этих средах - это использовать только установщик параметров и получатель ResultSet, которые принимают Календарь, и убедиться, что каждое приложение, которое обращается к данным, использует какой-то календарь, предпочтительно GMT или UTC.

...