MybatisPlus更新為null的字段及自定義sql注入
mybatis-plus在執(zhí)行更新操作,當(dāng)更新字段為 空字符串 或者 null 的則不會(huì)執(zhí)行更新。如果要將指定字段更新null,可以通過(guò)以下四種方式實(shí)現(xiàn)
1、全局配置(不推薦)
可以在 application.yml 配置文件中注入配置 GlobalConfiguration 屬性 update-strategy,
將 update-strategy 策略調(diào)整為 IGNORED,即忽略判斷策略。即可調(diào)整全局的驗(yàn)證策略。
# yml 配置: mybatis-plus: global-config: db-config: update-strategy: IGNORED
2、添加updateStrategy 注解(不推薦)
在實(shí)體類中將需要更新為null的字段上添加updateStrategy 注解,并將更新策略設(shè)置為IGNORED。
@TableField(value = "name", updateStrategy=FieldStrategy.IGNORED) private String name;
3、使用UpdateWrapper更新(當(dāng)屬性很多寫(xiě)起來(lái)很麻煩)
通過(guò)baseMapper的UpdateWrapper將實(shí)體類的指定字段set為null。
baseMapper.update(sysUser, Wrappers.<SysUser>lambdaUpdate() .set(SysUser::getOrgId, null) .set(SysUser::getOrgName, null) .eq(SysUser::getId, sysUser.getId()) );
4、Mybatis Plus 自定義SqlInjector sql注入器(推薦)
(1)、自定義sql注入器MySqlInjector
import com.baomidou.mybatisplus.core.injector.AbstractMethod; import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector; import com.baomidou.mybatisplus.core.metadata.TableInfo; import java.util.List; public class MySqlInjector extends DefaultSqlInjector { @Override public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) { List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo); // 根據(jù)id更新所有數(shù)據(jù) methodList.add(new UpdateWithNullMethod()); return methodList; } }
(2)、方法對(duì)應(yīng)的實(shí)現(xiàn)類UpdateWithNullMethod
import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.core.injector.AbstractMethod; import com.baomidou.mybatisplus.core.metadata.TableFieldInfo; import com.baomidou.mybatisplus.core.metadata.TableInfo; import com.baomidou.mybatisplus.core.toolkit.StringPool; import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils; import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.SqlSource; import java.lang.reflect.Field; import java.util.List; import static java.util.stream.Collectors.joining; /** * @author :zzt */ @Slf4j public class UpdateWithNullMethod extends AbstractMethod { protected UpdateWithNullMethod() { super("updateWithNull"); } @Override public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) { String sql = "<script>\nupdate %s %s where %s=#{%s}\n</script>"; final List<TableFieldInfo> fieldList = tableInfo.getFieldList(); for (TableFieldInfo tableFieldInfo : fieldList) { final Class<? extends TableFieldInfo> aClass = tableFieldInfo.getClass(); try { final Field fieldFill = aClass.getDeclaredField("fieldFill"); fieldFill.setAccessible(true); fieldFill.set(tableFieldInfo, FieldFill.UPDATE); } catch (NoSuchFieldException | IllegalAccessException e) { log.error("獲取fieldFill失敗", e); } } String setSql = this.sqlSet(tableInfo); String sqlResult = String.format(sql, tableInfo.getTableName(), setSql, tableInfo.getKeyColumn(), tableInfo.getKeyProperty()); log.debug("sqlResult----->{}", sqlResult); SqlSource sqlSource = languageDriver.createSqlSource(configuration, sqlResult, modelClass); // 第三個(gè)參數(shù)必須和rootMapper的自定義方法名一致 return this.addUpdateMappedStatement(mapperClass, modelClass, "updateWithNull", sqlSource); } protected String sqlSet(TableInfo table) { String sqlScript = table.getFieldList() .stream().map(i -> this.getSqlSet(i, StringPool.EMPTY)).collect(joining(StringPool.NEWLINE)); sqlScript = SqlScriptUtils.convertTrim(sqlScript, "SET", null, null, ","); return sqlScript; } public String getSqlSet(TableFieldInfo i, String prefix) { String newPrefix = prefix == null ? StringPool.EMPTY : prefix; String column = i.getColumn(); String update = i.getUpdate(); FieldFill fieldFill = i.getFieldFill(); String el = i.getEl(); // 默認(rèn):column= String sqlSet = column + StringPool.EQUALS; if (StringUtils.isNotEmpty(update)) { sqlSet += String.format(update, column); } else { sqlSet += SqlScriptUtils.safeParam(newPrefix +el); } sqlSet += StringPool.COMMA; if (fieldFill == FieldFill.UPDATE || fieldFill == FieldFill.INSERT_UPDATE) { // 不進(jìn)行if包裹 return sqlSet; } return convertIf(sqlSet, convertIfProperty(newPrefix, column), i.getUpdateStrategy(), i.getPropertyType().isPrimitive(), StringUtils.isCharSequence(i.getPropertyType())); } private String convertIfProperty(String prefix, String property) { return StringUtils.isNotBlank(prefix) ? prefix.substring(0, prefix.length() - 1) + "['" + property + "']" : property; } private String convertIf(final String sqlScript, final String property, final FieldStrategy fieldStrategy, boolean isPrimitive, boolean isCharSequence) { if (fieldStrategy == FieldStrategy.NEVER) { return null; } if (isPrimitive || fieldStrategy == FieldStrategy.IGNORED) { return sqlScript; } if (fieldStrategy == FieldStrategy.NOT_EMPTY && isCharSequence) { return SqlScriptUtils.convertIf(sqlScript, String.format("%s != null and %s !=''", property, property), false); } return SqlScriptUtils.convertIf(sqlScript, String.format("%s != null", property), false); } }
(2)、自定義基礎(chǔ)Mapper繼承BaseMapper
import com.baomidou.mybatisplus.core.mapper.BaseMapper; /** * @description: 自定義mapper借口,mybatisPlus * @author: zzt */ public interface MyBaseMapper<T> extends BaseMapper<T> { /** * 全字段更新,更新為null的字段 * @param obj 待更新對(duì)象 * @return 是否成功 */ boolean updateWithNull(T obj); }
最后直接調(diào)用即可。
到此這篇關(guān)于MybatisPlus更新為null的字段及自定義sql注入的文章就介紹到這了,更多相關(guān)MybatisPlus更新為null內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SimpleDateFormat線程安全問(wèn)題排查詳解
這篇文章主要為大家介紹了SimpleDateFormat線程安全問(wèn)題排查詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11Java?根據(jù)XPATH批量替換XML節(jié)點(diǎn)中的值
這篇文章主要介紹了Java根據(jù)XPATH批量替換XML節(jié)點(diǎn)中的值,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-09-09解決HashMap多線程操作導(dǎo)致死循環(huán)問(wèn)題
文章主要講述了在多線程環(huán)境下,HashMap的并發(fā)操作可能導(dǎo)致的死循環(huán)問(wèn)題,包括鏈表/紅黑樹(shù)結(jié)構(gòu)破壞、擴(kuò)容過(guò)程中的混亂以及讀寫(xiě)不一致等,為了解決這些問(wèn)題,文章建議使用線程安全的ConcurrentHashMap替代HashMap,并介紹了其分段鎖機(jī)制和優(yōu)化方案2025-01-01在Java中關(guān)閉SQL執(zhí)行日志來(lái)優(yōu)化服務(wù)器性能
Java應(yīng)用程序中,數(shù)據(jù)庫(kù)操作是一個(gè)常見(jiàn)的任務(wù),如果不適當(dāng)?shù)靥幚鞸QL執(zhí)行日志,可能會(huì)導(dǎo)致不必要的性能損失,SQL執(zhí)行日志通常由數(shù)據(jù)庫(kù)連接池、ORM框架(如Hibernate、MyBatis)、或者應(yīng)用服務(wù)器的內(nèi)置日志機(jī)制生成,本文將探討如何在Java中關(guān)閉SQL執(zhí)行日志,提升應(yīng)用性能和效率2024-11-11詳解基于Spring Data的領(lǐng)域事件發(fā)布
這篇文章主要介紹了詳解基于Spring Data的領(lǐng)域事件發(fā)布,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04Springboot整合JPA配置多數(shù)據(jù)源流程詳解
這篇文章主要介紹了Springboot整合JPA配置多數(shù)據(jù)源,JPA可以通過(guò)實(shí)體類生成數(shù)據(jù)庫(kù)的表,同時(shí)自帶很多增刪改查方法,大部分sql語(yǔ)句不需要我們自己寫(xiě),配置完成后直接調(diào)用方法即可,很方便2022-11-11JAVA CountDownLatch(倒計(jì)時(shí)計(jì)數(shù)器)用法實(shí)例
這篇文章主要介紹了JAVA CountDownLatch(倒計(jì)時(shí)計(jì)數(shù)器)用法實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10Java中的logback標(biāo)記日志過(guò)濾器MarkerFilter詳解
這篇文章主要介紹了Java中的logback標(biāo)記日志過(guò)濾器MarkerFilter詳解,在logback-classic中存在一個(gè)全局過(guò)濾器TurboFilter,TurboFilter是與LoggerContext綁定,會(huì)在會(huì)在其它過(guò)濾器之前執(zhí)行,需要的朋友可以參考下2023-11-11Java Springboot 重要知識(shí)點(diǎn)整理匯總
Spring Boot作為微服務(wù)中最好的Java框架,本文主要為大家整理匯總了七個(gè)Spring Boot的重要知識(shí)點(diǎn),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2021-11-11