【问题标题】:Caused by: java.lang.ClassCastException: java.sql.Timestamp cannot be cast to java.sql.Date原因:java.lang.ClassCastException:java.sql.Timestamp 无法转换为 java.sql.Date
【发布时间】:2014-09-17 13:47:45
【问题描述】:

我收到以下代码 sn-ps 的以下给定错误:

  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 是从哪里来的。

【问题讨论】:

  • 给我你的完整课程,然后我可以帮助你
  • 我们需要看一下CachedRowSetImpl和MyClass的代码。
  • 这有帮助吗http://stackoverflow.com/questions/20130129/error-java-sql-timestamp-cannot-be-cast-to-java-sql-date-in-jfreechart
  • @BrunoFranco: CachedRowSetImpl 来自import com.sun.rowset.CachedRowSetImpl;
  • @Abhi:这对我不起作用。我的列的值为18-09-14,类型为DATE

标签: java classcastexception cachedrowset


【解决方案1】:

已过时:

使用java.util.Date 作为字段。 java.sql.Timestamp 是它的直接子类。与java.sql.Date 一样 - 剥离了时间部分。为什么 java 数据库驱动程序将 DATE 用作 Timestamp 有点奇怪。什么是数据库供应商?您是否指定了长度?确实只存储日期吗?


已研究:

我查看了CachedRowSetImpl.java,Oracle 的文档和 Oracle 的一切都很好(java.sql.Date、java.sql.Time、java.sql.Timestamp 可转换)。 CachedRowSetImpl 只是简单地将 DATE 的对象(并且 getObject 很可能返回高分辨率时间戳 - 随时间)转换为 java.sql.Date,这是错误的。 所以 overridesubstitute 这个 sun 的类。

      /*
       * 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);
       }

【讨论】:

  • 数据库是Oracle 11g。除此之外, String , double 等都在使用,这很好。
  • 让我检查一下。因此,即使列类型为 DATE(根据注释行),我们也不能期望从 db 列返回 DATE 对象?
  • 另外,如果我输入new java.util.Date() 而不是cRows.getDate("PREV_DATE"),错误就消失了。所以我们可以确认返回的对象不是DATE...对吗?
  • 如果调用ResultSet.getDate("PREV_DATE") 很好,Timestamp ts = rs.getTimestamp("PREV_DATE") 应该是可能的,我猜rs.getObject("PREV_DATE") 会产生一个时间戳。罪魁祸首是 CachedRowImpl。
  • 您可以从 CachedRowImpl 覆盖 getDate 并强制转换为 java.util.Date。
【解决方案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

oracle doc 分享了不同的解决方案:

  • 更改您的表以使用 TIMESTAMP 而不是 DATE。这大概是 很少有可能,但它是最好的解决方案。

  • 更改您的应用程序以使用 defineColumnType 来定义列 作为 TIMESTAMP 而不是 DATE。这是有问题的,因为 你真的不想使用 defineColumnType 除非你必须(见 什么是defineColumnType,我应该什么时候使用它? )。

  • 更改您的应用程序以使用 getTimestamp 而不是 getObject。这 在可能的情况下是一个很好的解决方案,但是许多应用程序包含 依赖于 getObject 的通用代码,因此并不总是可行的。

  • 设置 V8Compatible 连接属性。这告诉 JDBC 驱动程序 使用旧映射而不是新映射。您可以设置此标志 作为连接属性或系统属性。你设置 通过将连接属性添加到 java.util.Properties 对象 传递给 DriverManager.getConnection 或 OracleDataSource.setConnectionProperties。您设置系统属性 通过在您的 java 命令行中包含 -D 选项。

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

这里是链接:http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-faq-090281.html#08_00

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-03
    • 2015-09-22
    • 2016-05-01
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    相关资源
    最近更新 更多