Mybatis-Plus自定义集合类型的类型处理器详解

 更新时间:2022年1月13日 16:46  点击:646 作者:nasoda_pro1993

两种方法,第一种很麻烦,对mp自带的插入操作有限制,后来改为更简洁的第二种方法

1.配合xml文件

TypeHandler

/**
 * 描述:fastjson的集合对象类型处理器,将mysql表中的json字段映射到实体类中的{@code List<?>}属性
 * 对照MP自带的FastjsonTypeHandler,自带的类型处理器会把所有的{@code List<?>}都会解析为{@code List<JsonObject>},
 * 这样在遍历其中对象时,调用对象属性的get、set方法就会发送类型转换JsonObject->?,这种情况转换错误。
 * 该处理器必须配合xml文件使用,不然无法获取要解析的对象类型,同时不能配合MP自带的{@link com.baomidou.mybatisplus.annotation.TableField}
 * 使用,默认情况下@TableField会将JavaType设置为字段的类型,如果是List<?>则type = List.class,无法明确其中的泛型,类型转换会变成JsonObject。
 * 用法:
 * <pre>{@code
 * 1.实体类上使用注解@TableName(value = "表名", resultMap = "xml文件中的resultMap的id")
 * 2.xml文件中自定义resultMap并设置需要JSON转换的字段
 * <result property="实体类属性名" column="表字段名" javaType="List中的对象全类名,例如List<Email>,则JavaType为Email的全类名" typeHandler="自定义处理器全类名"/>
 * 3.自定义方法上的用法
 * @Mapper
 * public interface DemoDao extends BaseMapper<DemoEntity> {
 *    @Select("select * from demo where demo_id = #{demoId}")
 *    @ResultMap(value = "xml文件中的resultMap的id")
 *    List<DemoEntity> selectListByDemoId(Long demoId);
 * }
 * }</pre>
 */
@Slf4j
@MappedJdbcTypes(value = JdbcType.VARCHAR)
public class FastJsonArrayTypeHandler extends AbstractJsonTypeHandler<List<?>> { 
    private Class<?> type; 
    public FastJsonArrayTypeHandler(Class<?> type) {
        if (log.isTraceEnabled()) {
            log.trace("FastjsonTypeHandler(" + type + ")");
        }
        Assert.notNull(type, "Type argument cannot be null");
        this.type = type;
    }
 
    @Override
    protected List<?> parse(String json) {
        return JSON.parseArray(json, type);// 注意不要使用parseObject方法
    }
 
    @Override
    protected String toJson(List<?> obj) {
        return JSON.toJSONString(obj, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullListAsEmpty, SerializerFeature.WriteNullStringAsEmpty);
    } 
}

xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="a.b.dao.DemoDao">
    <resultMap type="a.b.entity.DemoEntity" id="demoMap">
        <result property="DemoInfo" column="demo_info" javaType="a.b.xx.DiseaseInfo" typeHandler="a.b.handler.FastJsonArrayTypeHandler"/>
    </resultMap>
</mapper>

Dao

@Mapper
public interface DemoDao extends BaseMapper<DemoEntity> {
    @Select("select * from demo where demo_id = #{demoId}")
    @ResultMap(value = "demoMap")
    List<DemoEntity> selectListByPlanId(Long demoId);
}

Entity

@Data
@TableName(value = "demo", resultMap = "demoMap")
public class DemoEntity implements Serializable {
    private static final long serialVersionUID = -1L;
 
    /**
     * 主键
     */
    @TableId
    private Long id;
    private Long demoId
    /**
     * json字段
     */
    private List<DemoInfo> demoInfo;
}

2.手动注册

TypeHandler

@Slf4j
@MappedJdbcTypes(value = JdbcType.VARCHAR)
public class FastJsonArrayTypeHandler<T> extends AbstractJsonTypeHandler<Object> { 
    private TypeReference<List<T>> type; 
    public FastJsonArrayTypeHandler(TypeReference<List<T>> type) {
        this.type = type;
    }
 
    @Override
    protected Object parse(String json) {
        return JSON.parseObject(json, type);
    }
 
    @Override
    protected String toJson(Object obj) {
        return JSON.toJSONString(obj, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullListAsEmpty, SerializerFeature.WriteNullStringAsEmpty);
    } 
}

初始化,剩下的bean和dao都不需要额外配置

/**
 * 描述:初始化配置
 * 手动注册类型处理器
 */
@Component
public class InitConfig implements CommandLineRunner {
    public static final com.alibaba.fastjson.TypeReference<List<DemoInfo>> F_DEMO_INFO = new com.alibaba.fastjson.TypeReference<List<DemoInfo>>() {
    };
    public static final TypeReference<List<DemoInfo>> M_DEMO_INFO = new TypeReference<List<DemoInfo>>() {
    };
    // mp自动装配时注入的factory,可用于获取mybatis的配置属性,这里用来获取类型处理器的注册器
    private final SqlSessionFactory factory;
 
    public InitConfig(SqlSessionFactory factory) {
        this.factory = factory;
    }
 
    /**
     * 注册类型处理器
     * <pre>{@code
     * 1.List<DemoInfo>类型处理器
     * ...
     * }</pre>
     *
     * @param args incoming main method arguments
     * @throws Exception on error
     */
    @SuppressWarnings("all")
    @Override
    public void run(String... args) throws Exception {
        TypeHandlerRegistry typeHandlerRegistry = factory.getConfiguration().getTypeHandlerRegistry();
        typeHandlerRegistry.register(M_DEMO_INFO, new FastJsonArrayTypeHandler(F_DEMO_INFO));
    }
}

目前方法二存在的缺陷:虽然新增、查询不存在问题,执行MP自带的更新操作时,parameterMap参数类型都是Object,不会经过自定义的TypeHandler处理,最后会把json对象直接set进去(update demo ..., demo_info = JSON对象 ...)导致报错

暂无优雅的解决方案,先做个记录 。以上为个人经验,希望能给大家一个参考,也希望大家多多支持猪先飞。

原文出处:https://blog.csdn.net/nasoda_pro1993/article/details/1039720

[!--infotagslink--]

相关文章

  • Mybatis Plus select 实现只查询部分字段

    这篇文章主要介绍了Mybatis Plus select 实现只查询部分字段的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-09-01
  • 解决Mybatis 大数据量的批量insert问题

    这篇文章主要介绍了解决Mybatis 大数据量的批量insert问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-01-09
  • mybatis-plus 表名添加前缀的实现方法

    这篇文章主要介绍了mybatis-plus 表名添加前缀的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-08-26
  • mybatis-plus 返回部分字段的解决方式

    这篇文章主要介绍了mybatis-plus 返回部分字段的解决方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-10-02
  • mybatis的Configuration详解

    这篇文章主要介绍了mybatis的Configuration详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-11-04
  • MyBatis-Plus自动填充功能失效导致的原因及解决

    这篇文章主要介绍了MyBatis-Plus自动填充功能失效导致的原因及解决,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-02-04
  • mybatis 返回Integer,Double,String等类型的数据操作

    这篇文章主要介绍了mybatis 返回Integer,Double,String等类型的数据操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-11-25
  • mybatis-plus 处理大数据插入太慢的解决

    这篇文章主要介绍了mybatis-plus 处理大数据插入太慢的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-12-18
  • MyBatisPlus-QueryWrapper多条件查询及修改方式

    这篇文章主要介绍了MyBatisPlus-QueryWrapper多条件查询及修改方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2022-06-27
  • 解决mybatis-plus 查询耗时慢的问题

    这篇文章主要介绍了解决mybatis-plus 查询耗时慢的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-07-04
  • 使用mybatis-plus报错Invalid bound statement (not found)错误

    这篇文章主要介绍了使用mybatis-plus报错Invalid bound statement (not found)错误,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-09-02
  • MyBatis-Plus的物理删除和逻辑删除(使用场景)

    数据库中的数据删除会分为两种:物理删除 和 逻辑删除,接下来通过本文给大家介绍MyBatis-Plus的物理删除和逻辑删除使用场景分析,感兴趣的朋友一起看看吧...2021-09-25
  • mybatis-plus实体类主键策略有3种(小结)

    这篇文章主要介绍了mybatis-plus实体类主键策略有3种(小结),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-08-27
  • Springboot如何使用mybatis实现拦截SQL分页

    这篇文章主要介绍了Springboot使用mybatis实现拦截SQL分页,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-06-19
  • Mybatis执行update失败的解决

    这篇文章主要介绍了Mybatis执行update失败的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-09-01
  • Mybatis plus中使用in查询出错如何解决

    这篇文章主要介绍了Mybatis plus中使用in查询出错的问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-08-06
  • 解决Mybatis中mapper.xml文件update,delete及insert返回值问题

    这篇文章主要介绍了解决Mybatis中mapper.xml文件update,delete及insert返回值问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-11-23
  • mybatis-plus雪花算法自动生成机器id原理及源码

    Mybatis-Plus是一个Mybatis的增强工具,它在Mybatis的基础上做了增强,却不做改变,Mybatis-Plus是为简化开发、提高开发效率而生,但它也提供了一些很有意思的插件,比如SQL性能监控、乐观锁、执行分析等,下面一起看看mybatis-plus雪花算法自动生成机器id原理解析...2021-06-04
  • mybatis-plus getOne和逻辑删除问题详解

    这篇文章主要介绍了mybatis-plus getOne和逻辑删除,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-08-26
  • Mybatis用注解写in查询的实现

    这篇文章主要介绍了Mybatis用注解写in查询的实现方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-07-13