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());