服务器为Tomcat5.0,配置好Oracle9.2的JNDI数据源,通过Context来获取javax.sql.DataSource,
然后再获取Connection。Oracle中表TEST001的字段G是TIMESTAMP类型,示例代码如下,注释为
其简单输出。
  InitialContext initCtx = ...
  Context ctx = initCtx.lookup(...);
  DataSource ds = (DataSource)ctx.lookup(...);
  Connection conn = ds.getConnection();//已经获取了Connection
  PreparedStatement ps = conn.prepareStatement("select g from test001 where a='ccc'");
  ResultSet rs = ps.executeQuery();
  
 
  while(rs.next()){
    Object obj = rs.getObject(1);
    out.println("getG:"+obj.getClass().getName()+"<BR>");//oracle.sql.TIMESTAMP
    out.println("getG:"+obj.getClass().isInstance(obj)+"<BR>");//true
    out.println("getG:"+oracle.sql.TIMESTAMP.class.isInstance(obj)+"<BR>");//false
    out.println("getG:"+oracle.sql.TIMESTAMP.class.equals(obj.getClass())+"<BR>");//false
    out.println("getG:"+oracle.sql.TIMESTAMP.class.equals(oracle.sql.TIMESTAMP.class)+"<BR>");//true
    out.println("getG:"+obj.getClass().equals(obj.getClass())+"<BR>");//true
    out.println("getG:"+obj.getClass().equals(oracle.sql.TIMESTAMP.class)+"<BR>");//false
    //out.println("getG:"+(oracle.sql.TIMESTAMP)obj+"<BR>");//该语句将抛出ClassCastException异常
  }
  conn.close();
请高手给解决一下这个问题,否则Oracle中的TIMESTAMP字段就永远无法取得正常值了。
必要说明:Connection如果是从DriverManager.getConnction(...)获取的话没有这个问题。
怀疑是commons-dbcp的问题。

解决方案 »

  1.   

    大部分连接池都会对jdbc的类进行再次封装,
    出于通用性,他们继承自 java.sql.Timestamp
    所以你转化为oracle.sql.TIMESTAMP 会抛出异常如果你用Weblogic的,你更不能直接用Oracle.sql 了,而必须用weblogc.thin.,,,, 之类的!
      

  2.   

    回复楼上的java2000_net :
    我知道它是进行了封装,不知道你有没有看过commons-dbcp 和 commons-pool的源代码,
    你会发现,从这里获得的ResultSet的确是经过封装的,但是请注意,他封装时,只是将
    实际生成的ResultSet传入到它的封装类中作为私有变量,然后针对所有封装类调用的方法
    都是直接从调用私有的这个ResulstSet的方法,因此,从道理上来讲,再怎么封装,它
    实现的功能都还是原来生成的ResultSet的功能;
    其次,请你注意一下继承体系,oracle.sql.TIMESTAMP 继承oracle.sql.Datum,
    oracle.sql.Datum 继承 Object,然后请再看清楚,我在这里根本就没有出现强制转换
    java.sql.Timestamp的,不要答非所问。最后,再说明一下,我提这个问题的要点:
    rs.getObject(1).getClass().getName()返回的是oracle.sql.TIMESTAMP,
    那么为什么这样的强制转换:
    (oracle.sql.TIMESTAMP)rs.getObject(1)
    会抛出ClassCastException?
      

  3.   

    好像还要加个 if 判断吧,即便rs.getObject(1)返回的是oracle.sql.TIMESTAMP
    如:if(obj instanceof oracle.sql.TIMESTAMP)
          out.println("getG:"+(oracle.sql.TIMESTAMP)obj+" <BR> ");
      

  4.   

    如果类的名称一致,还出现ClassCastException异常,则表明其ClassLoader不一致的问题所致。Tomcat服务器我不是很熟悉,猜测可能的问题是你的应用服务器和web应用都配置了不同的Oracle9.2的jdbc driver. 先将web应用的那个类路径删除试试。DriverManager.getConnction()是好的是因为它和oracle.sql.TIMESTAMP.class使用相同的ClassLoader。
      

  5.   

    回复 huoyin:我在  Object obj = rs.getObject(1) 下面加上两行:out.println(obj.getClass().getClassLoader()+"<BR>");                // Line 1
    out.println(oracle.sql.TIMESTAMP.class.getClassLoader()+"<BR>");    // Line 2发现,Line 1 的ClassLoader顺序为:StandardClassLoader  -> sun.misc.Launcher$AppClassLoader ;
         Line 2 的ClassLoader顺序为:WebClassLoader --> StandardClassLoader  -> sun.misc.Launcher$AppClassLoader ;
    确实表明是他们的 ClassLoader 是不一样的,你的结论完全正确,谢谢!
      

  6.   

      你打开oracle.sql.TIMESTAMP看看就明白了.
      

  7.   

    # java.util.Properties prop = new java.util.Properties ();   
    # prop.put ("oracle.jdbc.V8Compatible", "true"); // so getObject returns Timestamp!   
    # prop.put ("user", "scott");   
    # prop.put ("password", "tiger");   
    # String url ="jdbc:oracle:thin:@host:port:sid";   
      

  8.   

    我也遇到类似的问题,如果这样做:
    conn.prepareStatement("select g from test001 where a='ccc'",ResultSet.TYPE_SCROLL_INSENSITIVE);
    就可以了,这样可以防止Oracle的驱动对字段的类型进行修改,以仍然保持JDBC类型。