baomidou / mybatis-plus

An powerful enhanced toolkit of MyBatis for simplify development
https://baomidou.com
Apache License 2.0
16.47k stars 4.31k forks source link

自定义的TypeHandler在执行insert或updateById的时候会触发额外的实例化 #5952

Closed CrizyCat closed 10 months ago

CrizyCat commented 10 months ago

当前使用版本(必填,否则不予处理)

3.5.5 ### 该问题是如何引起的?(确定最新版也有问题再提!!!) 自定义的TypeHandler,构造方法的参数是Class[]> 在执行insert或updateById的时候会触发额外的实例化,传入类型为Object,@TableField标注的字段实际为正常的枚举数组 为了业务的正常进行,暂时将构造方法的类型检查注释了,但还是希望你们可以排查一下是什么原因导致的无效的额外的实例化TypeHandler ```java package com.vsupa.commons.config; import com.alibaba.fastjson2.JSON; import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.ibatis.type.JdbcType; import org.apache.ibatis.type.MappedJdbcTypes; import org.apache.ibatis.type.MappedTypes; @Slf4j @MappedTypes({Enum[].class}) @MappedJdbcTypes({JdbcType.VARCHAR}) public class EnumArrayTypeHandler extends AbstractJsonTypeHandler[]> { private final Class[]> type; public EnumArrayTypeHandler(Class[]> type) { log.info("EnumArrayTypeHandler:{}",type); this.type = type; if (!type.isArray()) { log.error("type is not array"); // throw new IllegalArgumentException("type is not array"); return; } if (!type.getComponentType().isEnum()){ log.error("type is not enum array"); // throw new IllegalArgumentException("type is not enum array"); } } public Enum[] parse(String json) { if(StringUtils.isBlank(json)){ return JSON.parseObject("[]", this.type); } return JSON.parseObject("[\"%s\"]".formatted(json.replaceAll(",", "\",\"")), this.type); } public String toJson(Enum[] obj) { if (obj == null) { return StringUtils.EMPTY; } return StringUtils.join(obj, ","); } } ``` ### 重现步骤(如果有就写完整) ### 报错信息 [2024-02-01 16:18:50.346] [INFO] [http-nio-8080-exec-6] [njMdmo.1706775530] [com.vsupa.commons.config.EnumArrayTypeHandler] >>> EnumArrayTypeHandler:class java.lang.Object [2024-02-01 16:18:50.347] [ERROR] [http-nio-8080-exec-6] [njMdmo.1706775530] [o.a.c.c.C.[.[localhost].[/].[dispatcherServlet]] >>> Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.mybatis.spring.MyBatisSystemException] with root cause java.lang.IllegalArgumentException: type is not array
miemieYaho commented 10 months ago

insert和update等于你在xml里的sql,#{xx,typehandler=xxx.xx.xx.xx},那必然每次都会实例化

DanteCY commented 5 months ago

我也遇到了.我是在字段上加了 @TableField(typeHandler = EnumOrdinalTypeHandler.class) 然后调用mapper本身的updateById的时候触发了EnumOrdinalTypeHandler的实例化.但是传的参数是一个object.然后就更新失败了.