Подтвердить что ты не робот

Почему бы не использовать java.util.Date в Jdbc?

Это простой вопрос: я знаю и слышал от почти всех, что использование java.util.Date для чего-либо в вызове Jdbc - плохая идея. Вы должны использовать либо java.sql.Date, либо java.sql.Time или java.sql.Timestamp. Однако в чем причина этого? Я не могу найти хорошее сообщение в блоге или сообщение SO, объясняющее это, за исключением того, что иногда люди видят "странное поведение".

Спасибо!

ИЗМЕНИТЬ

Итак, я видел этот пост. Да, единственная часть этой должности, которая отвечает на мой вопрос:

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

Однако это не отвечает на почему.

4b9b3361

Ответ 1

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

Настройка:

Из того, что я вижу, есть три слоя

JDBC wrapper calls (e.g. Spring SimpleJdbcTemplate)
|
|
Raw JDBC calls (e.g. PreparedStatement)
|
|
JDBC driver (e.g. Oracle)

Первый Причина

Многие обертки класса JDBC, такие как Spring известный SimpleJdbcTemplate, позволили вам дать ему Map<String, Object> как карту аргументов при выполнении инструкции SQL. Это удивительно просто, поскольку он передает все преобразования из объектов в соответствующие типы java.sql.*, когда он использует необработанный JDBC под капотом. Первая проблема здесь: что произойдет, если у вас есть следующее:

Map<String, Object> paramMap = new HashMap<String,Object>();
paramMap.put("p_some_data", new java.util.Date());

Что делает Spring конвертировать его? A java.sql.Date? A java.sql.Timestamp? A java.sql.Time? Или он даже отбрасывает его на java.lang.Object? Как объяснил @BalusC в этот ответ на другой вопрос и другой человек здесь, существуют большие различия между этими тремя типами java.sql. Итак, первая причина не использовать java.util.Date: вы не можете полагаться на внутреннее соглашение рамки для обработки преобразования для вас.

Второй разум

Теперь, говоря о необработанных вызовах JDBC, @Nail объяснил, что вам нужны эти типы java.sql для вызова JDBC, а он абсолютно прав, который для меня был новостью. Тем не менее, по-прежнему существует страшный вызов setObject. Из чтения JavaDoc для этого вызова кажется немного неопределенным в отношении того, что он будет делать, если дать java.util.Date. Таким образом, вторая причина не использовать его из-за двусмысленности там.

Третий разум

Наконец, поговорим об уровне драйвера. Я могу подтвердить с личным опытом, что иногда Spring в сочетании с драйвером Oracle работает с java.util.Date. Иногда. И иногда это не так. Поэтому, поскольку я не знаю, как любая конкретная версия любого конкретного драйвера будет обрабатывать java.util.Date, лучше всего быть явным. Это третья причина.

Заключение

В общем, похоже, что причина: "JDBC не предполагается использовать с java.util.Date. Если вы это сделаете, вы не можете быть уверены, что произойдет". Это для меня достаточно хорошая причина:)

Ответ 2

java.sql.Timestamp

Тонкая оболочка вокруг java.util.Date, которая позволяет API JDBC идентифицировать это как значение SQL TIMESTAMP. Он добавляет возможность удерживать значение дробных секунд SQL TIMESTAMP, позволяя задавать дробные секунды точности наносекунд. Временная метка также обеспечивает операции форматирования и разбора для поддержки синтаксиса escape-кода JDBC для значений метки времени.

Это уровень точности метки времени (предоставленной БД), которую он может удерживать vs java.util.Date.

Предположим, если мы используем объект java.util.Date для представления значения временной метки в БД, тогда значение, представленное объектом, не будет представлять одно и то же значение (как в БД), поскольку оно не может удерживать эти "дробные секунды до точность наносекунд".

Ответ 3

Что касается Date, это довольно просто: PreparedStatement.setDate требуется java.sql.Date, а не java.util.Date.

Вы можете конвертировать из java.util.Date в java.sql.Date так:

java.sql.Date sqlDate = new java.sql.Date(date.getTime());

Ответ 4

 java.util.Date 

представляет общее значение DateTime. Как правило, тип Java.

 java.sql.Date

Специфичен для сопоставления объектной модели объекта Java с типом данных SQL, который предназначен для данных SQL. (Тип Sql, а не тип Java).