Mybaits/Mybatis-Plus JSON字段类型转换

142 阅读2分钟

Mybaits/Mybatis-Plus JSON字段类型转换

注意:

框架不支持泛型转换 例如:List 的泛型转换,默认查找第一个List类型的TypeHandler

一、Mybatis

  • 实现BaseTypeHandler抽象类型进行类型转换,可以去copy一下Mybatis-Plus下com.baomidou.mybatisplus.extension.handlers包中的几个通用Handler,或者自己实现BaseTypeHandler

01.jpg

  • 使用Handler,result标签typeHandler字段设置自定义Handler完整包路径 eg:

    <result property="attachments" column="attachments" typeHandler="com.business.handler.AttachmentHandler"/>
    

二、Mybatis-Plus

  • 简单类型转换com.baomidou.mybatisplus.extension.handlers下的几个handler选一个就ok,如下:
    @TableField(typeHandler = JacksonTypeHandler.class)
    private Demo demo;

三、泛型处理

由于不支持泛型,我们曲线救国,下面我们以List 为例子

  1. 继承ArrayList,封装我们自己的List

    import java.util.ArrayList;
    
    public class StringList extends ArrayList<String> {
    }
    
    
  2. 封装对应的Handler处理 自定义泛型注解 配合Handler处理泛型解析问题,value -> 泛型,List value -> String.class

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    public @interface MappedTypeGeneric {
        Class<?> value();
    }
    

    抽象类型Handler List处理

    import com.alibaba.fastjson2.JSON;
    import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler;
    import org.apache.ibatis.type.MappedTypes;
    
    import java.lang.reflect.Type;
    import java.util.ArrayList;
    
    public abstract class AbstractListJsonTypeHandler<T extends ArrayList<?>> extends AbstractJsonTypeHandler<T> {
    
        @Override
        protected T parse(String json) {
    
            try {
                if (json == null || json.trim().isEmpty()) {
                    return createEmptyInstance();
                }
                T result = createEmptyInstance();
                result.addAll(JSON.parseArray(json, getElementType()));
                return result;
            } catch (Exception e) {
                return null;
            }
        }
    
        @Override
        protected String toJson(T obj) {
            if (obj != null) {
                return JSON.toJSONString(obj);
            }
            return null;
        }
    
        /**
         * 创建空的集合实例
         */
    
        protected T createEmptyInstance() {
            try {
                Class<?> listClass = getClass()
                        .getAnnotation(MappedTypes.class).value()[0];
                return (T) listClass.getDeclaredConstructor().newInstance();
            } catch (Exception e) {
                throw new IllegalStateException("Failed to create list instance", e);
            }
        }
    
        /**
         * 获取集合元素类型
         */
        protected Type getElementType(){
            //获取注解值 MappedTypeGeneric
            return getClass().getAnnotation(MappedTypeGeneric.class).value();
        }
    }
    

createEmptyInstance也可以写成abstract抽象方法交给子类实现

StringListJsonTypeHandler 处理List 转换

import com.hm.pms.common.mybatis.lang.StringList;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

@MappedTypes(StringList.class)
@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypeGeneric(String.class)
public class StringListJsonTypeHandler extends AbstractListJsonTypeHandler<StringList>{
    @Override
    protected StringList createEmptyInstance() {
        return new StringList();
    }
}

使用

    @TableField(typeHandler = StringListJsonTypeHandler.class)
    private List<String> stringList;

这样子,我们就有了一个能处理所有List泛型的模版

第一步:自定义List继承ArrayList

第二步:自定义TypeHandler继承AbstractListJsonTypeHandler,添加@MappedTypeGeneric解析类型

第三步:使用TypeHandler进行转换

Spring开启mybatis-plus 自定义类型转换配置,扫描包下的handler

mybatis-plus:
  type-handlers-package: com.business.handler