MyBatis-Plus 自定义 TypeHandler 映射JSON类型为List

1 在mysql 5.7 支持json类型,那么在表实体是怎么运用的

在mybatis-plus 中有相关的handler

/**
 * Jackson 实现 JSON 字段类型处理器
 *
 * @author hubin
 * @since 2019-08-25
 */
@Slf4j
@MappedTypes({Object.class})
@MappedJdbcTypes(JdbcType.VARCHAR)
public class JacksonTypeHandler extends AbstractJsonTypeHandler<Object>

2.1 对象 json类型 List<字符串> json 类型

handler

@Slf4j
@MappedTypes({Object.class})
@MappedJdbcTypes(JdbcType.VARCHAR)
public class JacksonTypeHandler extends AbstractJsonTypeHandler<Object> {
    private static ObjectMapper OBJECT_MAPPER;
    private final Class<?> type;

    public JacksonTypeHandler(Class<?> type) {
        if (log.isTraceEnabled()) {
            log.trace("JacksonTypeHandler(" + type + ")");
        }
        Assert.notNull(type, "Type argument cannot be null");
        this.type = type;
    }

    @Override
    protected Object parse(String json) {
        try {
            return getObjectMapper().readValue(json, type);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    protected String toJson(Object obj) {
        try {
            return getObjectMapper().writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    public static ObjectMapper getObjectMapper() {
        if (null == OBJECT_MAPPER) {
            OBJECT_MAPPER = new ObjectMapper();
        }
        return OBJECT_MAPPER;
    }

    public static void setObjectMapper(ObjectMapper objectMapper) {
        Assert.notNull(objectMapper, "ObjectMapper should not be null");
        JacksonTypeHandler.OBJECT_MAPPER = objectMapper;
    }
}
    @TableField(typeHandler = JacksonTypeHandler.class)
    private List<String> tag;

    @TableField(typeHandler = JacksonTypeHandler.class)
    private Tag tag;

2.2 map handler

@MappedTypes( {JsonNode.class})
@MappedJdbcTypes( {JdbcType.VARCHAR})
@Component
public class MapTypeHandler extends AbstractJsonTypeHandler<Map<String, String>> {
    private static ObjectMapper objectMapper = new ObjectMapper();

    @Override
    protected Map<String, String> parse(String json) {
        return JsonUtils.string2Obj(json, Map.class);
    }

    @Override
    protected String toJson(Map<String, String> obj) {
        return obj.toString();
    }
}

@Data
@Schema(name = "ChatApi", description = "chat api 接口")
@TableName(value = "chat_api", autoResultMap = true)
@Accessors(chain = true)
public class ChatApi {
    /**
     * 主键 自增
     */
    @TableId(type = IdType.AUTO)
    @Schema(allowableValues = "ID")
    private String id;

    private String url;

    private String requestType;

    @TableField(typeHandler = MapTypeHandler.class)
    private Map<String, String> header;

    @TableField(typeHandler = MapTypeHandler.class)
    private Map<String, String> param;

    private String type;

    private String model;

    private Boolean status;
}

3 List<对象> json 类型

直接用默认的是不行的,虽然查询没有问题,但是对List操作是会有类型转换异常

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.ruleengine.model.rules.SeriesModel

那么我要自定义handler

1 ListTypeHandler

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

@MappedJdbcTypes(JdbcType.VARBINARY)
@MappedTypes( {List.class})
public abstract class ListTypeHandler<T> extends BaseTypeHandler<List<T>> {
    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int parameterIndex, List<T> parameter, JdbcType jdbcType)
        throws SQLException {
        String content = CollUtil.isEmpty(parameter) ? null : JSON.toJSONString(parameter);
        preparedStatement.setString(parameterIndex, content);
    }

    @Override
    public List<T> getNullableResult(ResultSet resultSet, String columnName) throws SQLException {
        return this.getListByJsonArrayString(resultSet.getString(columnName));
    }

    @Override
    public List<T> getNullableResult(ResultSet resultSet, int columnIndex) throws SQLException {
        return this.getListByJsonArrayString(resultSet.getString(columnIndex));
    }

    @Override
    public List<T> getNullableResult(CallableStatement callableStatement, int columnIndex) throws SQLException {
        return this.getListByJsonArrayString(callableStatement.getString(columnIndex));
    }

    private List<T> getListByJsonArrayString(String content) {
        return StrUtil.isBlank(content) ? new ArrayList<>() : JSON.parseObject(content, this.specificType());
    }

    /**
     * 具体类型,由子类提供
     *
     * @return 具体类型
     */
    protected abstract TypeReference<List<T>> specificType();
}

2 SeriesModelListTypeHandler

public class SeriesModelListTypeHandler extends ListTypeHandler<SeriesModel> {
    @Override
    protected TypeReference<List<SeriesModel>> specificType() {
        return new TypeReference<List<SeriesModel>>() { };
    }
}

3 运用

    @TableField(typeHandler = SeriesModelListTypeHandler.class)
    private List<SeriesModel> series;
posted @ 2023-12-11 09:25  linzm14  阅读(3132)  评论(0编辑  收藏  举报