Поздравляем, вы ударили мою любимую мозоль с JDBC: обработка класса Date.
Обычно базы данных поддерживают как минимум три формы полей даты и времени, которые представляют собой дату, время и метку времени. Каждый из них имеет соответствующий класс в JDBC и каждый из них расширяется java.util.Date
. Быстрая семантика каждого из этих трех:
java.sql.Date
соответствует SQL DATE, что означает, что он хранит годы, месяцы и дни , тогда как часы, минуты, секунды и миллисекунды игнорируются. Дополнительно sql.Date
не привязан к часовым поясам.
java.sql.Time
соответствует времени SQL и, как должно быть очевидно, содержит только информацию о часах, минутах, секундах и миллисекундах .
java.sql.Timestamp
соответствует SQL TIMESTAMP, который является точной датой наносекунды ( обратите внимание, что util.Date
поддерживает только миллисекунды! ) с настраиваемой точностью.
Одна из наиболее распространенных ошибок при использовании драйверов JDBC в отношении этих трех типов заключается в том, что типы обрабатываются неправильно. Это означает, что sql.Date
зависит от часового пояса, sql.Time
содержит текущий год, месяц и день и так далее и тому подобное.
Наконец: какой использовать?
Действительно зависит от типа поля SQL. PreparedStatement
имеет сеттеры для всех трех значений, #setDate()
- один для sql.Date
, #setTime()
для sql.Time
и #setTimestamp()
для sql.Timestamp
.
Обратите внимание, что если вы используете ps.setObject(fieldIndex, utilDateObject);
, вы на самом деле можете дать обычное util.Date
большинству драйверов JDBC, которые с радостью пожрут его, как если бы он был правильного типа, но когда вы запросите данные впоследствии, вы можете заметить, что вы на самом деле скучаете.
Я действительно говорю, что ни одна из дат не должна использоваться вообще.
То, что я говорю, сохраняйте миллисекунды / наносекунды в виде простых длинных и конвертируйте их в любые объекты, которые вы используете ( обязательный штекер времени joda ). Один хакерский способ, который можно сделать, - это сохранить компонент даты как один компонент времени и времени как другой, например, прямо сейчас будет 20100221 и 154536123. Эти магические числа можно использовать в запросах SQL и переносить из базы данных в другую и позволит вам полностью отказаться от этой части JDBC / Java Date API: