IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> MyBatis查询报错Error attempting to get column ‘x‘ from result Cause: com.alibaba.fastjson.JSONException -> 正文阅读

[大数据]MyBatis查询报错Error attempting to get column ‘x‘ from result Cause: com.alibaba.fastjson.JSONException

?

问题分析及解决方案

由于该字段是有单选改为多选,该字段的历史数据的格式不是JSONArray形式,所以导致查询结果类型与实体类中不匹配。
解决方案(建议使用第一种,不影响历史数据):

一、修改该字段的历史数据为JSONArray类型;
update deal_base a set fund_type = concat('["', a.fund_type, '"]');
二、删除该字段的历史数据;

该问题产生的背景

该错误出现的情况:数据表中有一个字段是fund_type,该字段用于存储基金的类型。起初设计的是基金类型单选(下拉单选),后来发现多选更适合,因此就把web页面上的改字段改为了多选,从而导致出现JSONException。

起初是这样的:

单选下拉??

后来变成这样的:

下拉多选

简述:

就是把下拉单选换成了下拉多选。在这里我把原来的实体类字段属性变成了JSONArray以便将整个数组存入到数据库中。

    /**
     * 基金类型Str
     */
    @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的转换。附插件代码(具体代码及作用网上都是,不赘述):

/**
 * @author Sophia
 *
 * @description 用以mysql中varchar格式的字段,进行转换的自定义转换器,转换为实体类的JSONArray属性
 */
@MappedTypes(JSONArray.class)
@MappedJdbcTypes(JdbcType.VARCHAR)
public class JsonTypeHandler extends BaseTypeHandler<JSONArray> {

    /**
     * 重写设置参数
     * @param ps
     * @param i
     * @param parameter
     * @param jdbcType
     * @throws SQLException
     */
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, JSONArray parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, String.valueOf(parameter.toJSONString()));
    }

    /**
     * 根据列名,获取可以为空的结果
     * @param rs
     * @param columnName
     * @return
     * @throws SQLException
     */
    @Override
    public JSONArray getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String sqlJson = rs.getString(columnName);
        if (null != sqlJson){
            return JSONObject.parseArray(sqlJson);
        }
        return null;
    }

    /**
     * 根据列索引,获取可以为空的结果
     * @param rs
     * @param columnIndex
     * @return
     * @throws SQLException
     */
    @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字段使用自定义插件匹配,如下(根据自己的情况二选一):

	<!--设置别名 column要和别名保持一致-->
    <resultMap id="BaseResultMapJSON" type="com.anxin.deal.warehousing.entity.DealFofWarehousing">
        <result column="fundType" property="fundType" typeHandler="com.anxin.common.mybatis.JsonTypeHandler" />
    </resultMap>
	<!--未设置别名,column要和数据库字段保持一致-->
	    <resultMap id="BaseResultMapJSON" type="com.anxin.deal.warehousing.entity.DealFofWarehousing">
        <result column="fund_type" property="fundType" typeHandler="com.anxin.common.mybatis.JsonTypeHandler" />
    </resultMap>

定义了该resultMap后,要在有fundType的字段的方法返回类型中使用resultMap。如:

<select id="getById" parameterType="String" resultMap="BaseResultMapJSON">
        select 
        id as id,
        name as name,
        deal_type as dealType,
        fund_type as fundType,
        create_time as createTime,
        update_time as updateTime 
        from deal_fof_warehousing
        where  del_flag = '0' and  id = #{id}
    </select>
到此,大功告成!启动测试。

报错
查看日志输出:

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(<generated>)
	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字段的数据错误。

在数据库中查看该字段,发现该字段中有的值不是数组类型(历史数据的问题),所以导致数据获取异常。
报错根本
只需要将不是数据的数据该成数组数据,或将不是数组的数据删除即可完美解决该问题!

希望能帮助各位小伙伴!若有其他更好的方案,可关注评论!

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-03-10 22:36:15  更:2022-03-10 22:38:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 9:14:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码