关于解决JFINAL和ORACLE使用过程中renderJson中Timestamp问题

环境:jFinal3.3和Oracle 11g2

问题:Oracle的Timestamp类型在renderJson后无法正确显示时间

现象:

 1.建表语句(创建了2个时间类型字段 test_data和test_times)

create table test(

id varchar(35) primary key,

test_date DATE,

test_times TIMESTAMP

)

2.添加测试数据,并自动生成model

image.png

3.控制层使用renderJson方法

image.png

4.访问控制层得到json

[{"ID":"1","TEST_DATE":"2017-12-11 17:47:46","TEST_TIMES":{"stream":{},"bytes":[120,117,12,11,18,48,50],"length":7}}]

注:在默认情况下Oracle的DATE字段能正常得到,但Oracle的Timestamp字段值解析便出了异常。

注:因为在renderJson判断时,oracle.sql.Timestamp没有与if分支相匹配,最后走的是value = rs.getObject(i),导致oracle.sql.Timestamp;如图(图中文件所在地址:com.jfinal.plugin.activerecord.builder.KeepByteAndShortModelBuilder中的build方法)

image.png

5.解决方法一

使用fastJson

在Config中配置fastJson作为jfinal的默认实现

访问控制层测试

image.png

Timestamp时间显示正常

注:该对象的model在自动生成时对oracle的timestamp的get,set方法经过了处理

image.png

解决方式二:

使用默认Jfinal json实现,自己新建ModelBuilder覆盖原有的KeepByteAndShortModelBuilder实现,并切换到自己的ModelBuilder

在自己项目中新建一个类MyOracleModelBuilder,

public class MyOracleModelBuilder extends ModelBuilder{

public static final MyOracleModelBuilder me = new MyOracleModelBuilder();

@SuppressWarnings({"rawtypes", "unchecked"})

public <T> List<T> build(ResultSet rs, Class<? extends Model> modelClass) throws SQLException, InstantiationException, IllegalAccessException {

List<T> result = new ArrayList<T>();

ResultSetMetaData rsmd = rs.getMetaData();

int columnCount = rsmd.getColumnCount();

String[] labelNames = new String[columnCount + 1];

int[] types = new int[columnCount + 1];

buildLabelNamesAndTypes(rsmd, labelNames, types);

while (rs.next()) {

Model<?> ar = modelClass.newInstance();

Map<String, Object> attrs = CPI.getAttrs(ar);

for (int i=1; i<=columnCount; i++) {

Object value;

if(types[i] == Types.TIMESTAMP){

value = rs.getTimestamp(i);

}

else if(types[i] == Types.DATE){

value = rs.getDate(i);

}

else if (types[i] == Types.TINYINT)

value = rs.getByte(i);

else if (types[i] == Types.SMALLINT)

value = rs.getShort(i);

else if (types[i] < Types.BLOB)

value = rs.getObject(i);

else if (types[i] == Types.CLOB)

value = handleClob(rs.getClob(i));

else if (types[i] == Types.NCLOB)

value = handleClob(rs.getNClob(i));

else if (types[i] == Types.BLOB)

value = handleBlob(rs.getBlob(i));

else 

value = rs.getObject(i);

attrs.put(labelNames[i], value);

}

result.add((T)ar);

}

return result;

}

}

在源码的实现上新增2个if判断(加粗部分),然后在Config中切换到我们自定义MyOracleModelBuilder

image.png

查看效果

image.png

ok,大功告成。

快看看成功了吗?

评论区

ddjfinal

2017-12-12 18:39

说实话,数据量不是很大的小型系统,日期直接varchar存储,简单又方便,数据量很大或者拿日期字段做了索引的,还是老老实实的用日期类型吧!

Revil

2017-12-21 16:48

都不行啊 可以留个联系方式吗

加洲旅馆2012

2017-12-28 08:55

@Revil 已私信给你

hankingxu

2019-04-16 16:59

不中啊,咋解决的

热门分享

扫码入社