一个jdbc(setTimestamp())的bug?

Posted on 2008-03-26 17:17 bluoy 阅读(1782) 评论(0)  编辑  收藏
项目中组员偶然写了一段垃圾的sql语句,不想却误打误撞的发现了一个jdbc的bug,包括Oracle 10g附带的版本。

详细描述可以参考如下代码:
   public static void testSetTimestampBug() throws Exception{
        Calendar calendar = new GregorianCalendar();
        Date d = calendar.getTime();
        
        String sql = "select 1+1 from dual where ?-sysdate<1";         //error sql
        String sql1 = "select ?-sysdate from dual";                          //no error sql
        String sql2 = "select 1+1 from dual where ?-1<sysdate";       //no error sql
        PreparedStatement pst = cn.prepareStatement(sql);
        //pst.setDate(1, new java.sql.Date(d.getTime()));                 //no  error
        pst.setTimestamp(1, new java.sql.Timestamp(d.getTime()));   //bug!!!, throw SQLException: ORA-00932
    }
三种sql的写法中,第一种写法在使用setTimestamp()时会出错,其他俩种却不会有问题。
即正常调用PreparedStatement.setTimestamp()方法,遇到某些特殊写法的sql语句却会出错。
本例中,抛出如下例外:
java.sql.SQLException: ORA-00932: inconsistent datatypes: expected NUMBER got INTERVAL.
然而,如果使用setDate()方法,则一切正常,三种写法都没有问题。

因为有这个问题,如果在持久层使用了其他的中间件,则这个问题可能变的更加隐蔽,比如iBatis中的处理是这样的:
java.util.Date ---> ibatis.DateTypeHandler----->PreparedStatement.setTimestamp() 
java.sql.Date ---> ibatis.SqlDateTypeHandler----->PreparedStatement.setDate()
如果不注意输入参数类型的话,就会遇到上述问题。我就因此费了不少周折。
对于iBatis的使用建议,保证入口参数类型始终为java.sql.Date即可。


只有注册用户登录后才能发表评论。


网站导航: