项目情况:
应由客户要求需要将之前基于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
希望本解决方法对其他小伙伴有用。
后续会考虑引进为 OracleDialect 的默认支持