mybatis自定义TypeHandler反序列化

概述

有些场景需要将db中查出的值按照业务需要进行反序列化,在mybatis原生反序列化之后再去处理,需要多些几行代码,此时可以自定义属性的反序列化操作。

需求:
在sql查询的时候使用group_by_concat查询的结果是一个逗号分隔的字符串
例如"1,2,3,4"
java中想用List去接收

字符串自定义反序列化

封装共用泛型类

package com.xxx.xxx.xxx.xxx;

import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
import io.seata.common.util.StringUtils;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.springframework.core.ResolvableType;
import org.springframework.util.Assert;

import java.io.IOException;
import java.lang.reflect.Type;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class NestingJacksonTypeHandler<T> extends BaseTypeHandler<Object> {

    private JavaType javaType;

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();


    /**
     * 构造方法
     */
    public NestingJacksonTypeHandler() {
        ResolvableType resolvableType = ResolvableType.forClass(getClass());
        Type type = resolvableType.as(NestingJacksonTypeHandler.class).getGeneric().getType();
        javaType = constructType(type);
    }

    private static JavaType constructType(Type type) {
        Assert.notNull(type, "[Assertion failed] - type is required; it must not be null");
        return TypeFactory.defaultInstance().constructType(type);
    }


    private Object convertToEntityAttribute(String dbData) {
        if (StringUtils.isBlank(dbData)) {
            if (List.class.isAssignableFrom(javaType.getRawClass())) {
                return Collections.emptyList();
            } else if (Set.class.isAssignableFrom(javaType.getRawClass())) {
                return Collections.emptySet();
            } else if (Map.class.isAssignableFrom(javaType.getRawClass())) {
                return Collections.emptyMap();
            } else {
                return null;
            }
        }
        return toObject(dbData, javaType);
    }


    /**
     * 用jackson反序列化
     */
    private static <T> T toObject(String json, JavaType javaType) {
        Assert.hasText(json, "[Assertion failed] - this json must have text; it must not be null, empty, or blank");
        Assert.notNull(javaType, "[Assertion failed] - javaType is required; it must not be null");
        try {
            return OBJECT_MAPPER.readValue(json, javaType);
        } catch (com.fasterxml.jackson.core.JsonParseException e) {
            throw new RuntimeException(e.getMessage(), e);
        } catch (JsonMappingException e) {
            throw new RuntimeException(e.getMessage(), e);
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    /**
     * java属性映射db中的存储类型
     * 指定索引位置设置参数
     */
    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, Object o, JdbcType jdbcType) throws SQLException {
        preparedStatement.setString(i, JSONUtil.toJsonStr(o));
    }


    /**
     * 从db获取取出值后映射到java属性中
     * 根据columnName获取属性值
     */
    @Override
    public Object getNullableResult(ResultSet resultSet, String columnName) throws SQLException {
        String value = resultSet.getString(columnName);
        return convertToEntityAttribute(value);
    }

    /**
     * 从db获取取出值后映射到java属性中
     * 根据columnIndex获取属性值
     */
    @Override
    public Object getNullableResult(ResultSet resultSet, int columnIndex) throws SQLException {
        return convertToEntityAttribute(resultSet.getString(columnIndex));
    }

    /**
     * 从db获取取出值后映射到java属性中
     * 根据CallableStatement及columnIndex获取结果
     */
    @Override
    public Object getNullableResult(CallableStatement callableStatement, int columnIndex) throws SQLException {
        String value = callableStatement.getString(columnIndex);
        return convertToEntityAttribute(value);
    }
}

实际需要反序列化的属性的handler

package com.xxx.xxx.xxx.xxx;

import com.alibaba.fastjson.JSONObject;

/**
 * 反序列化JSONObject
 */
public class JsonObjectTypeHandler extends NestingJacksonTypeHandler<JSONObject>{
}

注解使用/xml使用

注解使用

class上需要声明autoResultMap = true,然后需要在配置文件中配置handler扫描路径

mybatis-plus:
	#(路径)
	type-handlers-package: com.package.handler
@Data
@TableName(value = "goods", autoResultMap = true)
public class Demo{

	@TableField(typeHandler = JsonObjectTypeHandler.class)
	private JSONObject reportContent;

}



xml中直接使用
可以不用再class上配置注解参数,也不需要配置文件扫描handler

<resultMap id="queryReportDataDetail" type="com.xxx.xxx.xxx.xxx.ReportDataDTO">
    <result property="reportId" column="id"/>
    <result property="skuNo" column="sku_no"/>
    <result property="reportContent" column="report_content" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/>
</resultMap>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值