MyBatis-Plus TypeHander不生效的問題解決
1 現(xiàn)象
mysql 使用json類型字段 存儲(chǔ)List<String>
,java類屬性使用TypeHandler 沒有生效。
代碼如下
實(shí)體類
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(); }
報(bào)錯(cuò)如下
關(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 的方法打了斷點(diǎn),還是沒有進(jìn)入斷點(diǎn)。
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 手動(dòng)轉(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更新某個(gè)屬性,該屬性的typehandler無效,需要手動(dòng)轉(zhuǎn)化或傳入typeHandler。
到此這篇關(guān)于MyBatis-Plus TypeHander不生效的問題解決的文章就介紹到這了,更多相關(guān)MyBatis-Plus TypeHander不生效內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Mybatis-plus自動(dòng)填充不生效或自動(dòng)填充數(shù)據(jù)為null原因及解決方案
- MyBatis-Plus分頁插件不生效的解決方法
- Mybatis-plus常見的坑@TableField不生效問題
- Mybatis-plus原生pages分頁未生效的解決方案
- mybatisplus?isNotNull不生效問題及解決
- Mybatis-plus 查詢條件為空不生效問題及解決
- MyBatis-Plus中MetaObjectHandler沒生效完美解決
- Mybatis使用update更新值為null時(shí)不生效問題解決
- mybatis-plus調(diào)用update方法時(shí),自動(dòng)填充字段不生效問題及解決
相關(guān)文章
使用JPA中@Query 注解實(shí)現(xiàn)update 操作方法(必看)
下面小編就為大家?guī)硪黄褂肑PA中@Query 注解實(shí)現(xiàn)update 操作方法(必看)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-06-06SpringBoot基于Mybatis攔截器和JSqlParser實(shí)現(xiàn)數(shù)據(jù)隔離
本文將介紹如何在 Spring Boot 項(xiàng)目中利用Mybatis的強(qiáng)大攔截器機(jī)制結(jié)合JSqlParser,一個(gè)功能豐富的 SQL 解析器,來輕松實(shí)現(xiàn)數(shù)據(jù)隔離的目標(biāo),本文根據(jù)示例展示如何根據(jù)當(dāng)前的運(yùn)行環(huán)境來實(shí)現(xiàn)數(shù)據(jù)隔離,需要的朋友可以參考下2024-04-04使用lombok@Data存在extends時(shí)需要注意的問題
在Java編程中,正確實(shí)現(xiàn)equals方法是保證對(duì)象比較一致性的關(guān)鍵,使用instanceof檢查類型可能導(dǎo)致違反對(duì)稱性原則,即當(dāng)子類和父類都重寫equals時(shí)可能出現(xiàn)a.equals(b)不等于b.equals(a)的情況,Lombok的@EqualsAndHashCode注解可以通過callSuper=true參數(shù)2024-10-10Idea如何使用System.getenv()獲取環(huán)境變量的值
文章介紹了如何在Java中使用`System.getenv()`方法讀取環(huán)境變量的值,并提供了兩種配置環(huán)境變量的方法:啟動(dòng)項(xiàng)配置和系統(tǒng)環(huán)境變量配置,對(duì)于系統(tǒng)環(huán)境變量,文章特別指出需要重啟電腦或程序才能使其生效2024-11-11深入解析面向?qū)ο缶幊淘贘ava中的應(yīng)用小結(jié)
本文詳細(xì)介紹了面向?qū)ο缶幊痰幕靖拍?包括類和對(duì)象、封裝、繼承和多態(tài),通過具體的Java代碼示例,展示了如何在Java中應(yīng)用這些面向?qū)ο缶幊痰暮诵乃枷?感興趣的朋友跟隨小編一起看看吧2025-01-01SpringBoot請(qǐng)求響應(yīng)方式示例詳解
這篇文章主要介紹了SpringBoot請(qǐng)求響應(yīng)的相關(guān)操作,本文通過示例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-06-06詳解SpringBoot如何優(yōu)雅的進(jìn)行全局異常處理
在SpringBoot的開發(fā)中,為了提高程序運(yùn)行的魯棒性,我們經(jīng)常需要對(duì)各種程序異常進(jìn)行處理,但是如果在每個(gè)出異常的地方進(jìn)行單獨(dú)處理的話,這會(huì)引入大量業(yè)務(wù)不相關(guān)的異常處理代碼,這篇文章帶大家了解一下如何優(yōu)雅的進(jìn)行全局異常處理2023-07-07