最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MyBatis-Plus TypeHander不生效的問題解決

 更新時間:2025年08月05日 11:35:05   作者:Always_July  
MyBatis-Plus中使用lambdaUpdate更新JSON字段時,TypeHandler未生效導(dǎo)致數(shù)據(jù)截斷錯誤,需手動轉(zhuǎn)換或顯式指定typeHandler解決,下面就來介紹一下該問題的解決

1 現(xiàn)象

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();
}

報錯如下

關(guān)鍵信息: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了一下,發(fā)現(xiàn)根本沒有解析出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,發(fā)現(xiàn)可以傳入mapping參數(shù),指定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);
}
/**
 * 設(shè)置 更新 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 手動轉(zhuǎn)為字符串

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.環(huán)境

mybatis-plus

<!--mybatis-plus-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.3.4</version>
</dependency>

5.總結(jié)

MyBatis-Plus 使用 lambdaUpdate更新某個屬性,該屬性的typehandler無效,需要手動轉(zhuǎn)化或傳入typeHandler。

到此這篇關(guān)于MyBatis-Plus TypeHander不生效的問題解決的文章就介紹到這了,更多相關(guān)MyBatis-Plus TypeHander不生效內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot中使用@Async實現(xiàn)異步調(diào)用?方法示例

    SpringBoot中使用@Async實現(xiàn)異步調(diào)用?方法示例

    在Spring Boot中異步調(diào)用是通過Spring的@Async注解來實現(xiàn)的,它允許我們在不阻塞主線程的情況下執(zhí)行耗時的操作,這篇文章主要介紹了SpringBoot中使用@Async實現(xiàn)異步調(diào)用?方法的相關(guān)資料,需要的朋友可以參考下
    2025-12-12
  • Spring實戰(zhàn)之Bean的作用域singleton和prototype用法分析

    Spring實戰(zhàn)之Bean的作用域singleton和prototype用法分析

    這篇文章主要介紹了Spring實戰(zhàn)之Bean的作用域singleton和prototype用法,結(jié)合實例形式分析了Bean的作用域singleton和prototype相關(guān)使用方法及操作注意事項,需要的朋友可以參考下
    2019-11-11
  • SpringBoot集成Druid監(jiān)控慢SQL的詳細(xì)過程

    SpringBoot集成Druid監(jiān)控慢SQL的詳細(xì)過程

    數(shù)據(jù)庫連接池是一個至關(guān)重要的組成部分,一個優(yōu)秀的數(shù)據(jù)庫連接池可以顯著提高應(yīng)用程序的性能和可伸縮性,常見的連接池:Druid、HikariCP、C3P0、DBCP等等,本文將詳細(xì)介紹如何在Spring Boot項目中配置數(shù)據(jù)源,集成Druid連接池,以實現(xiàn)更高效的數(shù)據(jù)庫連接管理
    2024-06-06
  • SpringBoot整合Mail發(fā)送郵件功能

    SpringBoot整合Mail發(fā)送郵件功能

    我們在網(wǎng)站上注冊賬號的時候一般需要獲取驗證碼,而這個驗證碼一般發(fā)送在你的手機號上還有的是發(fā)送在你的郵箱中,注冊,賬號密碼…都需要用到驗證,今天就演示一下如何用SpringBoot整合Mail發(fā)送郵箱
    2021-11-11
  • Java實現(xiàn)通過IP獲取IP歸屬地的方法(離線+在線)

    Java實現(xiàn)通過IP獲取IP歸屬地的方法(離線+在線)

    我們都知道安全攻擊都是在某臺客戶機上執(zhí)行某些惡意操作致使服務(wù)端響應(yīng)異常崩潰亦或響應(yīng)數(shù)據(jù)被篡改,首先我想到的是對訪問的web端做一個IP的校驗,那么我們首先得知道客戶端的IP是多少,接下來此文重點介紹如何獲得,需要的朋友可以參考下
    2023-10-10
  • Java的List集合框架之ArrayList詳解

    Java的List集合框架之ArrayList詳解

    這篇文章主要介紹了Java的List集合框架之ArrayList詳解,ArrayList默認(rèn)容量為10(構(gòu)造方法未指定初始容量為0),擴容是利用位運算(右移一位)和直接相加進行1.5倍擴容,需要的朋友可以參考下
    2023-11-11
  • MyBatis使用動態(tài)SQL標(biāo)簽的小陷阱

    MyBatis使用動態(tài)SQL標(biāo)簽的小陷阱

    MyBatis是一個支持普通SQL查詢,存儲過程和高級映射的優(yōu)秀持久層框架,MyBatis越來越受大家的喜愛了。下面給大家分享MyBatis使用動態(tài)SQL標(biāo)簽的小陷阱,感興趣的朋友一起看看吧
    2016-10-10
  • java實現(xiàn)上傳文件到FTP

    java實現(xiàn)上傳文件到FTP

    這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)上傳文件到FTP,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • synchronized底層原理之JVM層面的鎖實現(xiàn)細(xì)節(jié)與流程

    synchronized底層原理之JVM層面的鎖實現(xiàn)細(xì)節(jié)與流程

    本文從JVM底層視角,詳細(xì)拆解了synchronized的實現(xiàn)邏輯,涵蓋鎖的存儲載體(對象頭的MarkWord)、鎖的觸發(fā)指令(monitorenter/monitorexit指令和ACC_SYNCHRONIZED標(biāo)志位)以及鎖的調(diào)度機制,感興趣的朋友跟隨小編一起看看吧
    2026-01-01
  • Spring源碼BeanFactoryPostProcessor詳解

    Spring源碼BeanFactoryPostProcessor詳解

    BeanFactoryPostProcessor的執(zhí)行時機是在Spring掃描完成后,Bean初始化前,當(dāng)我們實現(xiàn)BeanFactoryPostProcessor接口,可以在Bean的初始化之前對Bean進行屬性的修改,下面通過本文看下Spring源碼分析-BeanFactoryPostProcessor的實例代碼,感興趣的朋友一起看看吧
    2021-11-11

最新評論

内江市| 芜湖县| 永寿县| 泰兴市| 凤庆县| 岗巴县| 射阳县| 固始县| 武鸣县| 横山县| 诸暨市| 盘锦市| 突泉县| 高平市| 大关县| 东兰县| 资兴市| 井研县| 团风县| 浏阳市| 锡林郭勒盟| 大庆市| 石景山区| 新昌县| 灯塔市| 石林| 冀州市| 东乡族自治县| 古浪县| 布拖县| 澄江县| 秭归县| 卢龙县| 饶平县| 安丘市| 乐东| 邹平县| 疏勒县| 高邮市| 汨罗市| 右玉县|