java.util.Date
против java.sql.Date
: когда использовать, что и почему?
Поздравляю, вы ударили мою любимую любимую мозоль с JDBC: обработка класса Дата.
В основном базы данных обычно поддерживают как минимум три формы полей даты и времени: дату, время и метку времени. Каждый из них имеет соответствующий класс в JDBC, и каждый из них расширяетсяjava.util.Date
. Быстрая семантика каждого из этих трех заключается в следующем:
java.sql.Date
соответствует SQL DATE, что означает, что он хранит годы, месяцы и дни, а часы, минуты, секунды и миллисекунды игнорируются. Дополнительно sql.Date
не привязан к часовым поясам.java.sql.Time
соответствует SQL TIME и, как должно быть очевидно, содержит только информацию о часах, минутах, секундах и миллисекундах .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-time plug ). Один хакерский способ, который можно сделать, - это сохранить компонент даты как один компонент времени и времени как другой, например, прямо сейчас будет 20100221 и 154536123. Эти магические числа можно использовать в запросах SQL, и они будут переносимы из базы данных в другую и позволит вам полностью избежать этой части JDBC / Java Date API.
ПОСЛЕДНЕЕ РЕДАКТИРОВАНИЕ: Начиная с Java 8, вы не должны использовать ни то,
java.util.Date
ни другое,java.sql.Date
если не можете избежать этого, и вместо этого предпочитаете использоватьjava.time
пакет (на основе Joda), а не что-либо еще. Если вы не на Java 8, вот оригинальный ответ:java.sql.Date
- когда вы вызываете методы / конструкторы библиотек, которые его используют (например, JDBC). Не иначе. Вы не хотите вводить зависимости в библиотеки баз данных для приложений / модулей, которые не имеют явного отношения к JDBC.java.util.Date
- при использовании библиотек, которые его используют. В противном случае, как можно меньше, по нескольким причинам:Это изменчиво, что означает, что вы должны делать защитную копию каждый раз, когда передаете или возвращаете из метода.
Он не очень хорошо справляется с датами, что, на мой взгляд, должно быть задом наперед людям, подобным вашей.
Теперь, потому что Джуд не выполняет свою работу очень хорошо,
Calendar
были введены ужасные классы. Они также изменчивы и с ними ужасно работать, и их следует избегать, если у вас нет выбора.Существуют лучшие альтернативы, такие как Joda Time API (
который может даже превратиться в Java 7 и стать новым официальным API для обработки дат- быстрый поиск говорит, что этого не произойдет).Если вы чувствуете, что излишне вводить новую зависимость, такую как Joda,
long
не так уж и плохо использовать поля для отметок времени в объектах, хотя я сам обычно оборачиваю их в juD при их передаче, для обеспечения безопасности типов и в качестве документации.источник
java.sql.Date
сPreparedStatement
etc! Но когда вы передаете его, используйте тот,LocalDate
который вы конвертируете, используяjava.sql.Date.valueOf
иjava.sql.Date.valueOf
при настройке, и конвертируйте его обратно как можно раньше, используяjava.sql.Date.toLocalDate
- опять же, потому что вы хотите задействовать java.sql как можно меньше, и потому что он изменчив.Единственное время для использования
java.sql.Date
вPreparedStatement.setDate
. В противном случае используйтеjava.util.Date
. Это говорит о том, чтоResultSet.getDate
возвращает a,java.sql.Date
но его можно назначить непосредственно ajava.util.Date
.источник
java.sql.Date
может быть назначено,java.util.Date
когда первое расширяет второе? Какой смысл вы пытаетесь сделать?У меня была та же проблема, самый простой способ вставить текущую дату в подготовленное заявление - это следующий:
источник
ТЛ; др
Не используйте ни
java.time.Instant
Заменяетjava.util.Date
java.time.LocalDate
Заменяетjava.sql.Date
ни
Оба эти класса ужасны, имеют недостатки в дизайне и реализации. Избегайте как
чумногокоронавируса .Вместо этого используйте классы java.time , определенные в JSR 310. Эти классы являются ведущей в отрасли средой для работы с обработкой даты и времени. Они вытесняют сплошь кровавые классы ужасно унаследованный , такие как
Date
,Calendar
,SimpleDateFormat
, и такие.java.util.Date
Первый
java.util.Date
предназначен для представления момента в UTC, что означает смещение от UTC, равное нулю часов, минут и секунд.java.time.Instant
Сейчас заменено на
java.time.Instant
.java.time.OffsetDateTime
Instant
является основным многокомпонентным классом java.time . Для большей гибкости используйтеOffsetDateTime
setZoneOffset.UTC
для той же цели: представление момента в UTC.Вы можете отправить этот объект в базу данных с помощью
PreparedStatement::setObject
с помощью JDBC 4.2 или более поздней версии.Загрузить.
java.sql.Date
java.sql.Date
Класс также страшно и устаревший.Этот класс предназначен для представления только даты, без времени суток и без часового пояса. К сожалению, при ужасном взломе дизайна этот класс наследует от
java.util.Date
которого представляет момент (дата с временем суток в UTC). Так что этот класс просто притворяется, что он только на дату, но на самом деле несет время суток и неявное смещение UTC. Это вызывает столько путаницы. Никогда не используйте этот класс.java.time.LocalDate
Вместо этого используйте,
java.time.LocalDate
чтобы отслеживать только дату (год, месяц, день месяца) без какого-либо времени суток, ни какого-либо часового пояса или смещения.Отправить в базу данных.
Загрузить.
О java.time
Java.time каркас встроен в Java 8 и более поздних версий. Эти классы вытеснять неприятные старые устаревшие классы даты и времени , такие как
java.util.Date
,Calendar
, иSimpleDateFormat
.Чтобы узнать больше, смотрите Oracle Tutorial . И поиск переполнения стека для многих примеров и объяснений. Спецификация JSR 310 .
Проект Joda-Time , находящийся сейчас в режиме обслуживания , рекомендует перейти на классы java.time .
Вы можете обмениваться объектами java.time напрямую с вашей базой данных. Используйте драйвер JDBC, соответствующий JDBC 4.2 или более поздней версии . Нет необходимости в строках, нет необходимости в
java.sql.*
классах.Где взять классы java.time?
источник
Класс java.util.Date в Java представляет определенный момент времени (например, .g., 2013 25 ноября 16:30:45 вплоть до миллисекунд), но тип данных DATE в БД представляет только дату (например, 2013 ноя 25). Чтобы не дать вам ошибочно предоставить объект java.util.Date в БД, Java не позволяет напрямую устанавливать параметр SQL в java.util.Date:
Но это все же позволяет вам сделать это принудительно / намеренно (тогда часы и минуты будут игнорироваться драйвером БД). Это делается с помощью класса java.sql.Date:
Объект java.sql.Date может хранить момент времени (так что его легко построить из java.util.Date), но выдает исключение, если вы попытаетесь задать его часами (чтобы реализовать его концепцию только дата). Ожидается, что драйвер БД распознает этот класс и просто использует 0 для часов. Попробуй это:
источник
java.util.Date
представляет определенный момент времени с точностью до миллисекунды. Он представляет информацию о дате и времени без часового пояса. Класс java.util.Date реализует интерфейс Serializable, Cloneable и Comparable. Он наследуетсяjava.sql.Date
,java.sql.Time
иjava.sql.Timestamp
интерфейсы.java.sql.Date
расширяет класс java.util.Date, который представляет дату без информации о времени и должен использоваться только при работе с базами данных. Чтобы соответствовать определению SQL DATE, значения миллисекунд, обернутыеjava.sql.Date
экземпляром, должны быть «нормализованы» путем установки часов, минут, секунд и миллисекунд на ноль в конкретном часовом поясе, с которым связан экземпляр.Он наследует все публичные методы ,
java.util.Date
такие какgetHours()
,getMinutes()
,getSeconds()
,setHours()
,setMinutes()
,setSeconds()
. Такjava.sql.Date
как информация о времени не хранится, она переопределяет все операции времениjava.util.Date
и все эти методы выдают,java.lang.IllegalArgumentException
если они вызываются, как очевидно из подробностей их реализации.источник