Java.lang.ClassCastException: oracle.sql.TIMESTAMP не может быть добавлено в java.sql.Timestamp

Я работаю над приложением, которое передает ResultSet по сети. Я закончил использование класса CachedRowSetImpl. Но когда я подключаюсь к БД Oracle, я получаю ошибку, подобную этой

java.lang.ClassCastException: oracle.sql.TIMESTAMP не может быть добавлено в java.sql.Timestamp

Пожалуйста, помогите.

Исходный код выглядит следующим образом:

ResultSet res = response.getResultSet(); //resultset from the server
while (res.next()) {
    Agent agent = new Agent();
    agent.setName(res.getString(2));
    agent.setMobile(res.getString(1));
    agent.setBalance(res.getLong(4));
    agent.setLastUpdate(res.getDate(3)); //date from the result set
    agent.setAccountNumber(res.getString(5));
}

Ошибка...

java.lang.ClassCastException: oracle.sql.TIMESTAMP не может быть добавлено в java.sql.Timestamp java.lang.ClassCastException: oracle.sql.TIMESTAMP не может быть добавлено в java.sql.Timestamp     на com.sun.rowset.CachedRowSetImpl.getDate(CachedRowSetImpl.java:2139)

Ответы

Ответ 1

В javadoc для ResultSet.getObject() указано, что тип JDBC должен быть сопоставлен с типом Java, как это предписывается спецификацией JDBC (TIMESTAMP → java.sqlTimestmp ):

Этот метод вернет значение данного столбца в виде Java объект. Тип объекта Java будет объектом Java по умолчанию тип, соответствующий типу столбца SQL, следуя отображению для встроенные типы, указанные в спецификации JDBC.

Как вы заметили, драйвер Oracle по умолчанию не соответствует стандартному и вместо него использует oracle.sql.TIMESTAMP (который не расширяет java.sql.Timestamp). Хорошей новостью является то, что вы можете принудительно выполнить соответствие JDBC, установив системное свойство oracle.jdbc.J2EE13Compliant на true во время запуска vm:

java -Doracle.jdbc.J2EE13Compliant=true YourApplication

или программно

System.getProperties().setProperty("oracle.jdbc.J2EE13Compliant", "true")

Как только вы это сделаете, getResult() вернет экземпляры java.sql.Timestamp, как и ожидалось.

Подробнее см. соответствующий раздел в Документация драйвера JDBC Oracle, в которой описаны несколько способов установки oracle.jdbc.J2EE13Compliant.

Ответ 2

Я нашел выход.

 oracle.sql.TIMESTAMP ts = (oracle.sql.TIMESTAMP) res.getObject("last_update");
 agent.setLastUpdate(new Date(ts.dateValue().getTime()));

Ответ 3

Это связано с тем, что oracle.sql.TIMESTAMP не получен из java.sql.TIMESTAMP:

java.lang.Object
  -> oracle.sql.Datum
     -> oracle.sql.TIMESTAMP

Вы не можете перенести первое в более поздний.

Вместо этого используйте oracle.sql.TIMESTAMP.timestampValue():

public Timestamp timestampValue(Calendar cal) throws SQLException

Вызывает toTimestamp для преобразования внутреннего Oracle Date и Calendar в Java Timestamp.

Ответ 4

Я думаю, проблема в том, что ваш setLastUpdate ожидает объект типа java.sql.Date.

Теперь, когда вы используете agent.setLastUpdate(res.getDate(3));

res.getDate(3) должен возвращать объект, который ваш метод не ожидает, поэтому для этого может быть ClassCastException.

Попробуйте этот код и посмотрите, решит ли он вашу проблему или нет:

agent.setLastUpdate(new java.util.Date(res.getDate(3).getTime()));

Ответ 5

Скорее всего, вы использовали getTIMESTAMP() вместо getTIMESTAMP(). Методы getTIMESTAMP()getDATE() являются расширениями в OracleResultSet, которые возвращают специфические типы Oracle.

Если нет, то вы не используете драйвер JDBC, потому что возвращаемый тип getDATE() равен java.sql.Date, а getTIMESTAMP() - java.sql.Timestamp, поэтому он не может быть совсем другого типа, как в вашем вопросе.

Ответ 6

Это можно решить, используя функцию timestampValue(), присутствующую в классе oracle.sql.TIMESTAMP. Этот метод преобразует oracle.sql.TIMESTAMP в java.sql.Timestamp.

oracle.sql.TIMESTAMP ts = (oracle.sql.TIMESTAMP) res.getObject( "last_update" );  agent.setLastUpdate(ts.timestampValue());