欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

MybatisPlus如何自定义TypeHandler映射JSON类型为List

程序员文章站 2022-06-17 21:26:19
目录自定义typehandler映射json类型为list1. 实体类2. listtypehandler3. reportuserlisttypehandler4. java 泛型自定义typeha...

自定义typehandler映射json类型为list

1. 实体类

这里只展示需要映射的字段,分别在所需映射的字段和实体类上添加注解。 

@data
@tablename(value = "report", autoresultmap = true)
public class report { 
    private static final long serialversionuid = 1l; 
    @apimodelproperty("id")
    @tableid(value = "id", type = idtype.auto)
    private integer id;
 
    @apimodelproperty("报名信息")
    @tablefield(typehandler = reportuserlisttypehandler.class)
    private list<reportuser> reportinfo; 
}

2. listtypehandler

提供一个 jsonarray 转换为 java list集合的处理器

import cn.hutool.core.collection.collutil;
import cn.hutool.core.util.strutil;
import com.alibaba.fastjson.json;
import com.alibaba.fastjson.typereference;
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 ps, int i, list<t> parameter, jdbctype jdbctype) throws sqlexception {
        string content = collutil.isempty(parameter) ? null : json.tojsonstring(parameter);
        ps.setstring(i, content);
    }
 
    @override
    public list<t> getnullableresult(resultset rs, string columnname) throws sqlexception {
        return this.getlistbyjsonarraystring(rs.getstring(columnname));
    }
 
    @override
    public list<t> getnullableresult(resultset rs, int columnindex) throws sqlexception {
        return this.getlistbyjsonarraystring(rs.getstring(columnindex));
    }
 
    @override
    public list<t> getnullableresult(callablestatement cs, int columnindex) throws sqlexception {
        return this.getlistbyjsonarraystring(cs.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();  
}

3. reportuserlisttypehandler

由具体的子类提供list集合泛型类型

import com.alibaba.fastjson.typereference;
import com.hanku.business.model.reportuser; 
import java.util.list;  

public class reportuserlisttypehandler extends listtypehandler<reportuser> { 
    @override
    protected typereference<list<reportuser>> specifictype() {
        return new typereference<list<reportuser>>() {
        };
    }    
}

4. java 泛型

如果在 listtypehandler 类中直接提供 typereference<list<t>> 这种类型,那就等效于typereference<list<object>> 这种类型,后续 fastjson 在转换时无法确定具体的 java 类型,转换后的类型最终就会是 list<jsonobject> ;同理,如果使用 jackson 作为 json 转换工具,不确定具体类型时,最总会被转换为linkedhashmap 类型,都需要再使用 typereference 来转换一次。 

自定义typehandler的使用笔记

可通过自定义的typehandler实现某个属性在插入数据库以及查询时的自动转换,本例中是要将map类型的属性转化成clob,然后存入数据库。由于是复杂的map,mp自带的json转换器会丢失部分信息。

类型转换器还可以通过注解配置 java类型和jdbc类型

  • @mappedtypes:注解配置 java 类型
  • @mappedjdbctypes:注解配置 jdbc 类型

定义

@slf4j
@mappedtypes({object.class})
@mappedjdbctypes(jdbctype.varchar)
public class weightlisttypehandler  extends abstractjsontypehandler<object> {
    private static gson gson = new gson();
    private final class<?> type;
    public weightlisttypehandler(class<?> type) {
        if (log.istraceenabled()) {
            log.trace("weightlisttypehandler(" + type + ")");
        }
        assert.notnull(type, "type argument cannot be null");
        this.type = type;
    }
    @override
    protected object parse(string json) {
        type type1 = new typetoken<map<string, list<weightitem>>>(){}.gettype();
        return gson.fromjson(json, type1);
    }
    @override
    protected string tojson(object obj) {
        return gson.tojson(obj);
    }
    public static void setgson(gson gson) {
        assert.notnull(gson, "gson should not be null");
        weightlisttypehandler.gson = gson;
    }
}

使用

注意@tablename 注解 autoresultmap 属性

@data
@noargsconstructor
@tablename(value = "mix_target",autoresultmap = true)
public class mixtarget extends model<mixtarget> {
    @tableid(value = "id", type = idtype.auto)
    private long id;
    /**
     *指标描述
     */
    @tablefield("description")
    private string description;
    /**
     * 指标名
     */
    @tablefield("name")
    private string name;
    /**
     * 对应属性名
     */
    @tablefield("property_name")
    private string propertyname;
    /**
     * 起始点类型
     */
    @tablefield("source_type")
    private string sourcetype;
    /**
     * 属性对应权值列表
     * key 属性名 value指定条件下的权值
     */
    @tablefield(value = "weight_list",typehandler = weightlisttypehandler.class,jdbctype = jdbctype.clob)
    private map<string, list<weightitem>> weightlist;
    /**
     * 运行状态
     * 0 新建未运行
     * 1 运行中
     * 2 已运行 成功
     * 3 已运行 失败
     */
    @tablefield("status")
    private integer status;
    /**
     * 是否可用
     * 1 true
     * 0 false
     */
    @tablefield("enable")
    private integer enable;
    @tablefield("create_time")
    private localdatetime createtime;
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。