当前位置: 代码网 > it编程>编程语言>Java > MyBatis-Plus TypeHander不生效的问题解决

MyBatis-Plus TypeHander不生效的问题解决

2025年08月05日 Java 我要评论
1 现象mysql 使用json类型字段 存储list<string>,java类属性使用typehandler 没有生效。代码如下实体类import com.baomidou.mybat

1 现象

mysql 使用json类型字段 存储list<string>,java类属性使用typehandler 没有生效。

代码如下

实体类

import com.baomidou.mybatisplus.annotation.tablefield;
import com.baomidou.mybatisplus.extension.handlers.fastjsontypehandler;
public class messagedo {
        @tablefield(typehandler = fastjsontypehandler.class)
        private list<string> notifytype;
   
    }

service 层

@override
public void messageupdate(messageupdatereqdto reqdto) {
    lambdaupdate()
            .set(partnerdo::getwxnotifytype,reqdto.getwxnotifytype())
            .eq(partnerdo::getcompanyid,reqdto.getcompanyid())
            .update();
}

报错如下

关键信息:data truncation: cannot create a json value from a string with character set 'binary'.

 cause: com.mysql.cj.jdbc.exceptions.mysqldatatruncation: data truncation: cannot create a json value from a string with character set 'binary'.
; data truncation: cannot create a json value from a string with character set 'binary'.; nested exception is com.mysql.cj.jdbc.exceptions.mysqldatatruncation: data truncation: cannot create a json value from a string with character set 'binary'.
	at org.springframework.jdbc.support.sqlstatesqlexceptiontranslator.dotranslate(sqlstatesqlexceptiontranslator.java:104)
	at org.springframework.jdbc.support.abstractfallbacksqlexceptiontranslator.translate(abstractfallbacksqlexceptiontranslator.java:72)
	at org.springframework.jdbc.support.abstractfallbacksqlexceptiontranslator.translate(abstractfallbacksqlexceptiontranslator.java:81)
	at org.springframework.jdbc.support.abstractfallbacksqlexceptiontranslator.translate(abstractfallbacksqlexceptiontranslator.java:81)
	at org.mybatis.spring.mybatisexceptiontranslator.translateexceptionifpossible(mybatisexceptiontranslator.java:88)
	at org.mybatis.spring.sqlsessiontemplate$sqlsessioninterceptor.invoke(sqlsessiontemplate.java:440)
	at com.sun.proxy.$proxy146.update(unknown source)
	at org.mybatis.spring.sqlsessiontemplate.update(sqlsessiontemplate.java:287)
	at com.baomidou.mybatisplus.core.override.mybatismappermethod.execute(mybatismappermethod.java:64)
	at com.baomidou.mybatisplus.core.override.mybatismapperproxy$plainmethodinvoker.invoke(mybatismapperproxy.java:148)
	at com.baomidou.mybatisplus.core.override.mybatismapperproxy.invoke(mybatismapperproxy.java:89)
	at com.sun.proxy.$proxy238.update(unknown source)
	at com.baomidou.mybatisplus.extension.conditions.update.chainupdate.update(chainupdate.java:45)
	at com.baomidou.mybatisplus.extension.conditions.update.chainupdate.update(chainupdate.java:35)

令人疑惑,我明明配置typehandler,但是没有生效,在 com.baomidou.mybatisplus.extension.handlers.fastjsontypehandler#tojson 的方法打了断点,还是没有进入断点。

2.源码分析

typehandler的源码

com.baomidou.mybatisplus.core.mybatisparameterhandler#setparameters

public void setparameters(preparedstatement ps) {
    errorcontext.instance().activity("setting parameters").object(this.mappedstatement.getparametermap().getid());
    list<parametermapping> parametermappings = this.boundsql.getparametermappings();
    if (parametermappings != null) {
        for (int i = 0; i < parametermappings.size(); i++) {
            parametermapping parametermapping = parametermappings.get(i);
            if (parametermapping.getmode() != parametermode.out) {
                object value;
                string propertyname = parametermapping.getproperty();
                if (this.boundsql.hasadditionalparameter(propertyname)) { // issue #448 ask first for additional params
                    value = this.boundsql.getadditionalparameter(propertyname);
                } else if (this.parameterobject == null) {
                    value = null;
                } else if (this.typehandlerregistry.hastypehandler(this.parameterobject.getclass())) {
                    value = parameterobject;
                } else {
                    metaobject metaobject = this.configuration.newmetaobject(this.parameterobject);
                    value = metaobject.getvalue(propertyname);
                }
                typehandler typehandler = parametermapping.gettypehandler();
                jdbctype jdbctype = parametermapping.getjdbctype();
                if (value == null && jdbctype == null) {
                    jdbctype = this.configuration.getjdbctypefornull();
                }
                try {
                    typehandler.setparameter(ps, i + 1, value, jdbctype);
                } catch (typeexception | sqlexception e) {
                    throw new typeexception("could not set parameters for mapping: " + parametermapping + ". cause: " + e, e);
                }
            }
        }
    }
}

debug了一下,发现根本没有解析出typehandler

parametermapping 解析

org.apache.ibatis.builder.sqlsourcebuilder#parse

public staticsqlsource(configuration configuration, string sql, list<parametermapping> parametermappings) {
  this.sql = sql;
  this.parametermappings = parametermappings;
  this.configuration = configuration;
}

@override
public boundsql getboundsql(object parameterobject) {
  return new boundsql(configuration, sql, parametermappings, parameterobject);
}

org.apache.ibatis.builder.sqlsourcebuilder#parse

public sqlsource parse(string originalsql, class<?> parametertype, map<string, object> additionalparameters) {
  parametermappingtokenhandler handler = new parametermappingtokenhandler(configuration, parametertype, additionalparameters);
  generictokenparser parser = new generictokenparser("#{", "}", handler);
  string sql = parser.parse(originalsql);
  return new staticsqlsource(configuration, sql, handler.getparametermappings());
}

org.apache.ibatis.builder.sqlsourcebuilder.parametermappingtokenhandler#buildparametermapping

private parametermapping buildparametermapping(string content) {
  map<string, string> propertiesmap = parseparametermapping(content);
  string property = propertiesmap.get("property");
  class<?> propertytype;
  if (metaparameters.hasgetter(property)) { // issue #448 get type from additional params
    propertytype = metaparameters.getgettertype(property);
  } else if (typehandlerregistry.hastypehandler(parametertype)) {
    propertytype = parametertype;
  } else if (jdbctype.cursor.name().equals(propertiesmap.get("jdbctype"))) {
    propertytype = java.sql.resultset.class;
  } else if (property == null || map.class.isassignablefrom(parametertype)) {
    propertytype = object.class;
  } else {
    metaclass metaclass = metaclass.forclass(parametertype, configuration.getreflectorfactory());
    if (metaclass.hasgetter(property)) {
      propertytype = metaclass.getgettertype(property);
    } else {
      propertytype = object.class;
    }
  }
  parametermapping.builder builder = new parametermapping.builder(configuration, property, propertytype);
  class<?> javatype = propertytype;
  string typehandleralias = null;
  for (map.entry<string, string> entry : propertiesmap.entryset()) {
    string name = entry.getkey();
    string value = entry.getvalue();
    if ("javatype".equals(name)) {
      javatype = resolveclass(value);
      builder.javatype(javatype);
    } else if ("jdbctype".equals(name)) {
      builder.jdbctype(resolvejdbctype(value));
    } else if ("mode".equals(name)) {
      builder.mode(resolveparametermode(value));
    } else if ("numericscale".equals(name)) {
      builder.numericscale(integer.valueof(value));
    } else if ("resultmap".equals(name)) {
      builder.resultmapid(value);
    } else if ("typehandler".equals(name)) {
      typehandleralias = value;
    } else if ("jdbctypename".equals(name)) {
      builder.jdbctypename(value);
    } else if ("property".equals(name)) {
      // do nothing
    } else if ("expression".equals(name)) {
      throw new builderexception("expression based parameters are not supported yet");
    } else {
      throw new builderexception("an invalid property '" + name + "' was found in mapping #{" + content + "}.  valid properties are " + parameter_properties);
    }
  }
  if (typehandleralias != null) {
    builder.typehandler(resolvetypehandler(javatype, typehandleralias));
  }
  return builder.build();
}

lambdaupdate set源码

查看api,发现可以传入mapping参数,指定typehandler。

com.baomidou.mybatisplus.core.conditions.update.update#set(r, java.lang.object)

default children set(r column, object val) {
    return set(true, column, val);
}
default children set(boolean condition, r column, object val) {
    return set(condition, column, val, null);
}
/**
 * 设置 更新 sql 的 set 片段
 *
 * @param condition 是否加入 set
 * @param column    字段
 * @param val       值
 * @param mapping   例: javatype=int,jdbctype=numeric,typehandler=xxx.xxx.mytypehandler
 * @return children
 */
children set(boolean condition, r column, object val, string mapping);

3.解决方法

1 手动转为字符串

lambdaupdate()
        .set(partnerdo::getwxnotifytype,json.tojsonstring(reqdto.getwxnotifytype()))
        .eq(partnerdo::getcompanyid,reqdto.getcompanyid()) .update();

2 添加typehandler

lambdaupdate()
.set(partnerdo::getwxnotifytype,reqdto.getwxnotifytype(),"typehandler=com.baomidou.mybatisplus.extension.handlers.fastjsontypehandler")
        .eq(partnerdo::getcompanyid,reqdto.getcompanyid())
        .update();

4.环境

mybatis-plus

<!--mybatis-plus-->
<dependency>
    <groupid>com.baomidou</groupid>
    <artifactid>mybatis-plus-boot-starter</artifactid>
    <version>3.4.3.4</version>
</dependency>

5.总结

mybatis-plus 使用 lambdaupdate更新某个属性,该属性的typehandler无效,需要手动转化或传入typehandler。

到此这篇关于mybatis-plus typehander不生效的问题解决的文章就介绍到这了,更多相关mybatis-plus typehander不生效内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com