关于oracle数据库date类型赋予java.utilDate出现“无效的列类型”

项目情况:

应由客户要求需要将之前基于jfinal3.0开发的网站数据由mysql切换至oracle。

切换至oracle后,经测试反映所有涉及到date类型的数据表不管是新增/还是设置查询条件,均出现“无效的列类型”。

解决过程:

1、经过调试发现oracle数据库中Date列实际返回列类型未java.sql.Timestamp;我的第一反应就是更改参数类型,将之前java.util.Date类型改成java.sql.Timestamp,在我准备干的时候发现太多javabean都是使用java.uitl.Date类型,如果要改是一个巨大工程(虽然可以用查找/替换,但不知道更改类型后跟客户端交互是否有问题)。

2、继续进一步调试,发现jfinal在填充参数值的时候或调用不同方言去实现(MysqlDialect/OracleDialect等),而OracleDialect参数填充只对java.sql.Date,java.sql.timestamp做了处理,处理方式如下代码:

for (int i=0; i<paras.length; i++) {
            Object value = paras[i];
            if (value instanceof java.sql.Date) {
                pst.setDate(i + 1, (java.sql.Date)value);
            } else if (value instanceof java.sql.Timestamp) {
                pst.setTimestamp(i + 1, (java.sql.Timestamp)value);
            } else {
                pst.setObject(i + 1, value);
            }
        }

没有对java.util.Date类型的值进行处理,那我是不是可以直接集成然后重写改方法,自己加入对java.util.Date类型处理呢?说干就干,直接新建一个类CompatibleOracleDialect类,重写两个fillStatement方法,重写后代码如下:

    @Override
    public void fillStatement(PreparedStatement pst, List<Object> paras) throws SQLException {
        for (int i=0, size=paras.size(); i<size; i++) {
            Object value = paras.get(i);
            if (value instanceof java.sql.Date) {
                pst.setDate(i + 1, (java.sql.Date)value);
            } else if (value instanceof java.sql.Timestamp) {
                pst.setTimestamp(i + 1, (java.sql.Timestamp)value);
            } else if (value instanceof java.util.Date) {
                Date date = (Date)value;
                pst.setTimestamp(i + 1, new Timestamp(date.getTime()));
            }
else {
                pst.setObject(i + 1, value);
            }
        }
    }

    @Override
    public void fillStatement(PreparedStatement pst, Object... paras) throws SQLException {
        for (int i=0; i<paras.length; i++) {
            Object value = paras[i];
            if (value instanceof java.sql.Date) {
                pst.setDate(i + 1, (java.sql.Date)value);
            } else if (value instanceof java.sql.Timestamp) {
                pst.setTimestamp(i + 1, (java.sql.Timestamp)value);
            } else if (value instanceof java.util.Date) {
                Date date = (Date)value;
                pst.setTimestamp(i + 1, new Timestamp(date.getTime()));
            }
else {
                pst.setObject(i + 1, value);
            }
        }
    }

重写后,打包部署,测试,通过。

友情提示:记得将自己的jfinalConfig类数据库方言改成CompatibleOracleDialect

希望本解决方法对其他小伙伴有用。

评论区

JFinal

2017-08-18 11:36

这个方案是目前见过的最好的方案,非常赞,已收藏、点赞

后续会考虑引进为 OracleDialect 的默认支持

马小酱

2018-02-28 14:33

波总,这个问题现在还没有优化啊,我想问一下您当时设计的时候肯定考虑这个java.util.Date的问题了,当时是有什么思考嘛?

马小酱

2018-02-28 14:34

@JFinal 现在我还需要按照楼主的方式改啊,有没有更优化的方式?

热门分享

扫码入社