4

I am getting the below given error for the following code snippets:

  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.
        }
      }

Error:

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

In the database, the datatype for the column is DATE only. I am not able to figure out where the Timestamp is coming here.

5
  • give me your full classes then I can help you Commented Sep 17, 2014 at 13:49
  • We need to see the CachedRowSetImpl and MyClass code. Commented Sep 17, 2014 at 13:51
  • Does this help http://stackoverflow.com/questions/20130129/error-java-sql-timestamp-cannot-be-cast-to-java-sql-date-in-jfreechart Commented Sep 17, 2014 at 13:52
  • @BrunoFranco: CachedRowSetImpl is from import com.sun.rowset.CachedRowSetImpl; Commented Sep 17, 2014 at 13:59
  • @Abhi: That didn't work for me. The value for my column is 18-09-14 and is DATE in type. Commented Sep 17, 2014 at 14:05

2 Answers 2

6

Obsolete:

Use java.util.Date for the field. java.sql.Timestamp is a direct subclass of it. As is java.sql.Date - that strips the time part. Why the java database driver takes DATE to be Timestamp is a bit weird. What is the database vendor? Did you specify a length or so? Are indeed only dates stored?


Researched:

I looked into CachedRowSetImpl.java, and Oracle's docs and Oracle does everything fine (java.sql.Date, java.sql.Time, java.sql.Timestamp convertible). The CachedRowSetImpl does simply cast the DATE's Object (and getObject is likely to return the high resolution Timestamp - with time) to java.sql.Date, and that's wrong. So override or substitute this sun's class.

      /*
       * 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);
       }
Sign up to request clarification or add additional context in comments.

6 Comments

DB is Oracle 11g. Apart from this, String , double etc are using, which are fine.
Let me check this. So we can't expect a DATE object to be returned from a db column even if the column type is DATE (as per the commented lines)?
Also if I put new java.util.Date() instead of cRows.getDate("PREV_DATE") the error has gone. So we can confirm the object coming back is not DATE... right?
If calling ResultSet.getDate("PREV_DATE") fine, Timestamp ts = rs.getTimestamp("PREV_DATE") should be possible, and I guess that rs.getObject("PREV_DATE") yields a Timestamp. The culprit is CachedRowImpl.
You can override getDate from CachedRowImpl and do the cast to java.util.Date.
|
5

I have done a research on this issue and found some useful links. I found this confusion between DATE and TIMESTAMP is JDBC Driver specific. And most of the links suggest the use of -Doracle.jdbc.V8Compatible=true. For my JBoss I have set this in run.bat and the issue got resolved.

  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

The oracle doc shares different solutions:

  • Alter your tables to use TIMESTAMP instead of DATE. This is probably rarely possible, but it is the best solution when it is.

  • Alter your application to use defineColumnType to define the columns as TIMESTAMP rather than DATE. There are problems with this because you really don't want to use defineColumnType unless you have to (see What is defineColumnType and when should I use it? ).

  • Alter you application to use getTimestamp rather than getObject. This is a good solution when possible, however many applications contain generic code that relies on getObject, so it isn't always possible.

  • Set the V8Compatible connection property. This tells the JDBC drivers to use the old mapping rather than the new one. You can set this flag either as a connection property or a system property. You set the connection property by adding it to the java.util.Properties object passed to DriverManager.getConnection or to OracleDataSource.setConnectionProperties. You set the system property by including a -D option in your java command line.

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

Here is the link: http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-faq-090281.html#08_00

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.