Избегайте неявного преобразования даты в метку времени для выбора в Oracle с использованием Hibernate - PullRequest
2 голосов
/ 17 марта 2010

Я использую запросы критериев Hibernate 3.2.7.GA для выбора строк из базы данных Oracle Enterprise Edition 10.2.0.4.0 с фильтрацией по полю отметки времени. Данное поле имеет тип java.util.Date в Java и DATE в Oracle.

Оказывается , что поле отображается на java.sql.Timestamp, и Oracle преобразует все строки в TIMESTAMP перед сравнением с переданным значением, , минуя индекс и тем самым разрушительное представление.

Одним из решений было бы использование sqlRestriction() в Hibernate вместе с функцией TO_DATE в Oracle. Это могло бы улучшить производительность, но требует переписывания кода приложения (много запросов).

Так есть ли более элегантное решение? Поскольку Hibernate уже выполняет сопоставление типов, можно ли его настроить для правильной работы?

Обновление: Проблема возникает в различных конфигурациях, но вот один конкретный пример:

  • Oracle Enterprise Edition 10.2.0.4.0
  • Oracle JDBC Driver 11.1.0.7.0
  • Hibernate 3.2.7.GA
  • Oracle 10gDialect Hibernate
  • Java 1.6.0_16

Ответы [ 2 ]

0 голосов
/ 08 июня 2011

Согласно FAQ по Oracle JDBC :

"Драйверы 11.1 по умолчанию преобразуют SQL DATE в метку времени при чтении из базы данных"

Так что это ожидаемое поведение. Для меня это означает, что фактические значения из столбцов DATE преобразуются в java.sql.Timestamp, а не то, что переменные связывания с java.util.Date преобразуются в java.sql.Timestamp.

Вывод EXPLAIN PLAN поможет определить проблему. Кроме того, трассировка Oracle может точно сказать, какой тип назначен переменной bind в запросе.

Если это действительно так, то это может быть ошибка Oracle.

Вы можете обойти это следующим образом:

  • Создать ФБР ( Индекс на основе функций ) для столбца DATE, приведя его к TIMESTAMP. Например:

    CREATE INDEX tab_idx ON tab (CAST(date_col AS TIMESTAMP)) COMPUTE STATISTICS;
    
  • Создать представление, содержащее то же выражение CAST. Вы можете сохранить то же имя столбца, если хотите:

    CREATE VIEW v AS
    SELECT CAST(date_col AS TIMESTAMP) AS date_col, col_1, ... FROM tab;
    
  • Используйте представление вместо таблицы (во всяком случае, это хорошая идея, например, если вы уже использовали представление, вам вообще не нужно менять код). Когда переменная java.sql.Timestamp будет использоваться с date_col в условии WHERE, (если достаточно выборочно) будет использоваться индекс.

  • Если вы узнаете, почему возникла java.sql.Timestamp (или Oracle исправляет потенциальную ошибку), вы всегда можете вернуться, просто изменив Просмотр (и отбросив ФБР), и он будет полностью прозрачен для код

0 голосов
/ 17 марта 2010

Это может звучать радикально, но когда мы столкнулись с этой проблемой, мы в конечном итоге преобразовали все столбцы DATE в типы TIMESTAMP в базе данных. Я не вижу в этом никакого недостатка, и если Hibernate является вашей основной платформой приложений, вы спасете себя в будущем.

Примечания:

  • Типы столбцов могут быть изменены с простой "ALTER tableName MODIFY" columnName TIMESTAMP (precisionVal) ".

  • Я был удивлен, обнаружив, что индексы на этих столбцах не должно быть
    перестроен.

Опять же, это имеет смысл, только если вы привержены Hibernate.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...