Причина: java.lang.ClassCastException: java.sql.Timestamp не может быть приведен к java.sql.Date.

Я получаю приведенную ниже ошибку для следующих фрагментов кода:

  try {
        cRows = new CachedRowSetImpl();
        while(cRows.next()) 
        {
        MyClass myClass = new MyClass();
        myClass.setPrevDate(cRows.getDate("PREV_DATE")); // In debug mode, the error was throwing when I press Resume from here.
        }
      }

Ошибка:

Caused by: java.lang.ClassCastException: java.sql.Timestamp cannot be cast to java.sql.Date

В базе данных тип данных для столбца DATE только. Я не могу понять, где Timestamp придет сюда.

2 ответа

Решение

Я провел исследование по этой проблеме и нашел несколько полезных ссылок. Я обнаружил, что эта путаница между DATE и TIMESTAMP специфична для драйвера JDBC. И большинство ссылок предлагают использовать -Doracle.jdbc.V8Compatible=true, Для моего JBoss я установил это в run.bat и проблема была решена.

  1. https://community.oracle.com/thread/68918?start=0&tstart=0

  2. http://www.coderanch.com/t/90891/JBoss/oracle-jdbc-Compatible-true

  3. https://community.oracle.com/message/3613155

Оракул док разделяет различные решения:

  • Измените ваши таблицы, чтобы использовать TIMESTAMP вместо DATE. Это, вероятно, редко возможно, но это лучшее решение, когда оно есть.

  • Измените ваше приложение, чтобы использовать defineColumnType, чтобы определить столбцы как TIMESTAMP, а не как DATE. Есть проблемы с этим, потому что вы действительно не хотите использовать defineColumnType без необходимости (см. Что такое defineColumnType и когда мне его использовать?).

  • Измените ваше приложение, чтобы использовать getTimestamp, а не getObject. Это хорошее решение, когда это возможно, однако многие приложения содержат общий код, основанный на getObject, поэтому это не всегда возможно.

  • Установите свойство соединения V8Compatible. Это говорит драйверам JDBC использовать старое отображение, а не новое. Вы можете установить этот флаг либо как свойство соединения, либо как системное свойство. Вы устанавливаете свойство соединения, добавляя его в объект java.util.Properties, передаваемый DriverManager.getConnection или OracleDataSource.setConnectionProperties. Вы устанавливаете системное свойство, включив опцию -D в командную строку Java.

    java -Doracle.jdbc.V8Compatible = "true" MyApp

Вот ссылка: http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-faq-090281.html

Вышло из употребления:

использование java.util.Date для поля. java.sql.Timestamp это прямой подкласс этого. Как есть java.sql.Date - это лишает времени часть. Почему драйвер базы данных Java использует DATE как метку времени, немного странно. Кто является поставщиком базы данных? Вы указали длину или около того? Действительно ли хранятся только даты?


Исследуемый:

Я посмотрел в CachedRowSetImpl.java, и документы Oracle и Oracle все делают хорошо (java.sql.Date, java.sql.Time, java.sql.Timestamp Convertible). CachedRowSetImpl просто приводит объект DATE (и getObject, скорее всего, вернет метку времени с высоким разрешением - со временем) в java.sql.Date, и это неправильно. Так что переопределите или замените класс этого солнца.

      /*
       * The object coming back from the db could be
       * a date, a timestamp, or a char field variety.
       * If it's a date type return it, a timestamp
       * we turn into a long and then into a date,
       * char strings we try to parse. Yuck.
       */
       switch (RowSetMD.getColumnType(columnIndex)) {
           case java.sql.Types.DATE: {
               long sec = ((java.sql.Date)value).getTime();
               return new java.sql.Date(sec);
       }
Другие вопросы по тегам