解决复杂对象中数据类型变为LinkedHashMap,mysql中json字段使用mybatis-plus映射List<复杂对象>变为linkhashmap导致stream流操作等报错!

错误图片:

在这里插入图片描述

stream流操作时,报错:

java.lang.ClassCastException: class java.util.LinkedHashMap cannot be cast to class cn.df2680.luzhong.entity.po.inner.PaperModelCoord (java.util.LinkedHashMap is in module java.base of loader 'bootstrap'; cn.df2680.luzhong.entity.po.inner.PaperModelCoord is in unnamed module of loader 'app')
    at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178) ~[na:na]
    at java.base/java.util.AbstractList$RandomAccessSpliterator.forEachRemaining(AbstractList.java:720) ~[na:na]
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) ~[na:na]
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na]
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575) ~[na:na]
    at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260) ~[na:na]
    at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616) ~[na:na]
    at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622) ~[na:na]
    at java.base/java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627) ~[na:na]

提示List<[复杂对象]>中的类型时LinkHashMap而不是复杂对象中的对象类型。

经过排查,发现MySQL中有字段为json类型,且实体类有如下代码:

    @TableField(value = "coords", typeHandler = JacksonTypeHandler.class)
    private List<PaperModelCoord> coords;

其中PaperModelCoord定义如下:

public class PaperModelCoord extends Domain {

    /**
     * 第几页
     */
    private Integer page;

    private Coord topLeft;

    private Coord bottomRight;

    private Double pageWidth;

    private Double pageHeight;
}

可见其中不只有包装类,还有别的对象,所以是个复杂对象,而实体类转换器使用的是默认的typeHandler = JacksonTypeHandler.class,它会将复杂对象其中的对象序列化为linkedhashmap,如下图:
在这里插入图片描述

解决方法是实现自定义的json转换器:

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

import java.io.IOException;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

public class CustomTypeHandler extends BaseTypeHandler<List<复杂对象>> {

    private static final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, List<复杂对象> parameter, JdbcType jdbcType) throws SQLException {
        try {
            String json = objectMapper.writeValueAsString(parameter);
            ps.setString(i, json);
        } catch (JsonProcessingException e) {
            throw new SQLException("Error converting object to JSON string", e);
        }
    }

    @Override
    public List<复杂对象> getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String json = rs.getString(columnName);
        return parseJson(json);
    }

    @Override
    public List<复杂对象> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String json = rs.getString(columnIndex);
        return parseJson(json);
    }

    @Override
    public List<复杂对象> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String json = cs.getString(columnIndex);
        return parseJson(json);
    }

    private List<复杂对象> parseJson(String json) throws SQLException {
        if (json == null) {
            return null;
        }
        try {
            return objectMapper.readValue(json, objectMapper.getTypeFactory().constructCollectionType(List.class, 复杂对象.class));
        } catch (IOException e) {
            throw new SQLException("Error parsing JSON string", e);
        }
    }
}

然后在实体类上使用:

@TableField(value = "coords", typeHandler = CustomTypeHandler.class)
private List<复杂对象> coords;

问题就可以解决了。
其中mybatis-plus版本:3.5.5

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值