问题分析及解决方案由于该字段是有单选改为多选,该字段的历史数据的格式不是JSONArray形式,所以导致查询结果类型与实体类中不匹配。
解决方案(建议使用第一种,不影响历史数据):
update deal_base a set fund_type = concat('["', a.fund_type, '"]');
二、删除该字段的历史数据;
该问题产生的背景
该错误出现的情况:数据表中有一个字段是fund_type,该字段用于存储基金的类型。起初设计的是基金类型单选(下拉单选),后来发现多选更适合,因此就把web页面上的改字段改为了多选,从而导致出现JSONException。
起初是这样的:
后来变成这样的: 简述:就是把下拉单选换成了下拉多选。在这里我把原来的实体类字段属性变成了JSONArray以便将整个数组存入到数据库中。
@ApiModelProperty(value = "基金类型Str", position = 300)
private String fundTypeStr;
@ApiModelProperty(value = "基金类型", position = 300)
private JSonArray fundType;
public String getFundTypeStr() {
return fundTypeStr;
}
public void setFundTypeStr(String fundTypeStr) {
this.fundTypeStr = fundTypeStr;
}
public JSonArray getFundType() {
return fundType;
}
public void setFundType(JSonArray fundType) {
this.fundType = fundType;
}
在这里有一步很重要,就是需要实现Mybatis的插件,用于String和JSONArray的转换。附插件代码(具体代码及作用网上都是,不赘述):
@MappedTypes(JSONArray.class) @MappedJdbcTypes(JdbcType.VARCHAR) public class JsonTypeHandler extends baseTypeHandler{ @Override public void setNonNullParameter(PreparedStatement ps, int i, JSonArray parameter, JdbcType jdbcType) throws SQLException { ps.setString(i, String.valueOf(parameter.toJSONString())); } @Override public JSonArray getNullableResult(ResultSet rs, String columnName) throws SQLException { String sqlJson = rs.getString(columnName); if (null != sqlJson){ return JSONObject.parseArray(sqlJson); } return null; } @Override public JSonArray getNullableResult(ResultSet rs, int columnIndex) throws SQLException { String sqlJson = rs.getString(columnIndex); if (null != sqlJson){ return JSONObject.parseArray(sqlJson); } return null; } @Override public JSonArray getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { String sqlJson = cs.getString(columnIndex); if (null != sqlJson){ return JSONObject.parseArray(sqlJson); } return null; } }
在dao.xml中也要注意使用自定义的Mybatis插件进行转换(否则会无法正常启动系统)。
在xml文件中,我使用的是resultMap,将JSONArray字段使用自定义插件匹配,如下(根据自己的情况二选一):
定义了该resultMap后,要在有fundType的字段的方法返回类型中使用resultMap。如:
到此,大功告成!启动测试。
查看日志输出:
10:54:47.967 [http-nio-8088-exec-27] ERROR c.a.f.w.e.GlobalExceptionHandler - [handleException,84] - 错误代码:E380nested exception is org.apache.ibatis.executor.result.ResultMapException: Error attempting to get column 'fundType' from result set. Cause: com.alibaba.fastjson.JSONException: syntax error, expect [, actual error, pos 0, fieldName null org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.executor.result.ResultMapException: Error attempting to get column 'fundType' from result set. Cause: com.alibaba.fastjson.JSONException: syntax error, expect [, actual error, pos 0, fieldName null at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:77) at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:446) at com.sun.proxy.$Proxy120.selectList(Unknown Source) at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.java:230) at org.apache.ibatis.binding.MapperMethod.executeForMany(MapperMethod.java:139) at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:76) at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:59) at com.sun.proxy.$Proxy162.findSonListByDept(Unknown Source) at com.anxin.deal.base.service.DealbaseService.findList(DealbaseService.java:474) at com.anxin.deal.base.service.DealbaseService$$FastClassBySpringCGLIB$$9ffc5dd9.invoke() at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
报错了: exception is org.apache.ibatis.executor.result.ResultMapException: Error attempting to get column 'fundType' from result set. Cause: com.alibaba.fastjson.JSONException: syntax error, expect [, actual error, pos 0, fieldName null,
从字面意思不难理解是获取到fundType字段的数据错误。
在数据库中查看该字段,发现该字段中有的值不是数组类型(历史数据的问题),所以导致数据获取异常。
只需要将不是数据的数据该成数组数据,或将不是数组的数据删除即可完美解决该问题!



