Mybatis-Plus自定義集合類型的類型處理器詳解
兩種方法,第一種很麻煩,對(duì)mp自帶的插入操作有限制,后來改為更簡潔的第二種方法
1.配合xml文件
TypeHandler
/** ?* 描述:fastjson的集合對(duì)象類型處理器,將mysql表中的json字段映射到實(shí)體類中的{@code List<?>}屬性 ?* 對(duì)照MP自帶的FastjsonTypeHandler,自帶的類型處理器會(huì)把所有的{@code List<?>}都會(huì)解析為{@code List<JsonObject>}, ?* 這樣在遍歷其中對(duì)象時(shí),調(diào)用對(duì)象屬性的get、set方法就會(huì)發(fā)送類型轉(zhuǎn)換JsonObject->?,這種情況轉(zhuǎn)換錯(cuò)誤。 ?* 該處理器必須配合xml文件使用,不然無法獲取要解析的對(duì)象類型,同時(shí)不能配合MP自帶的{@link com.baomidou.mybatisplus.annotation.TableField} ?* 使用,默認(rèn)情況下@TableField會(huì)將JavaType設(shè)置為字段的類型,如果是List<?>則type = List.class,無法明確其中的泛型,類型轉(zhuǎn)換會(huì)變成JsonObject。 ?* 用法: ?* <pre>{@code ?* 1.實(shí)體類上使用注解@TableName(value = "表名", resultMap = "xml文件中的resultMap的id") ?* 2.xml文件中自定義resultMap并設(shè)置需要JSON轉(zhuǎn)換的字段 ?* <result property="實(shí)體類屬性名" column="表字段名" javaType="List中的對(duì)象全類名,例如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.手動(dòng)注冊(cè)
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都不需要額外配置
/** ?* 描述:初始化配置 ?* 手動(dòng)注冊(cè)類型處理器 ?*/ @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自動(dòng)裝配時(shí)注入的factory,可用于獲取mybatis的配置屬性,這里用來獲取類型處理器的注冊(cè)器 ? ? private final SqlSessionFactory factory; ? ? ? public InitConfig(SqlSessionFactory factory) { ? ? ? ? this.factory = factory; ? ? } ? ? ? /** ? ? ?* 注冊(cè)類型處理器 ? ? ?* <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)); ? ? } }
目前方法二存在的缺陷:雖然新增、查詢不存在問題,執(zhí)行MP自帶的更新操作時(shí),parameterMap參數(shù)類型都是Object,不會(huì)經(jīng)過自定義的TypeHandler處理,最后會(huì)把json對(duì)象直接set進(jìn)去(update demo ..., demo_info = JSON對(duì)象 ...)導(dǎo)致報(bào)錯(cuò)
暫無優(yōu)雅的解決方案,先做個(gè)記錄 。以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
MyBatis?@Select注解介紹:基本用法與動(dòng)態(tài)SQL拼寫方式
這篇文章主要介紹了MyBatis?@Select注解介紹:基本用法與動(dòng)態(tài)SQL拼寫方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07詳解Spring Cloud Consul 實(shí)現(xiàn)服務(wù)注冊(cè)和發(fā)現(xiàn)
這篇文章主要介紹了Spring Cloud Consul 實(shí)現(xiàn)服務(wù)注冊(cè)和發(fā)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-03-03淺談什么是SpringBoot異常處理自動(dòng)配置的原理
今天給大家?guī)淼氖顷P(guān)于Java的相關(guān)知識(shí),文章圍繞著SpringBoot異常處理自動(dòng)配置展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下2021-06-06