MybatisPlus更新为null的字段及自定义sql注入

 更新时间:2024年05月07日 10:56:37   作者:摆烂小赵  
mybatis-plus在执行更新操作,当更新字段为空字符串或者null的则不会执行更新,本文主要介绍了MybatisPlus更新为null的字段及自定义sql注入,感兴趣的可以了解一下

mybatis-plus在执行更新操作,当更新字段为 空字符串 或者 null 的则不会执行更新。如果要将指定字段更新null,可以通过以下四种方式实现

1、全局配置(不推荐)

可以在 application.yml 配置文件中注入配置 GlobalConfiguration 属性 update-strategy,

将 update-strategy 策略调整为 IGNORED,即忽略判断策略。即可调整全局的验证策略。

# yml 配置:
mybatis-plus:
  global-config:
    db-config:
      update-strategy: IGNORED

2、添加updateStrategy 注解(不推荐)

在实体类中将需要更新为null的字段上添加updateStrategy 注解,并将更新策略设置为IGNORED。

@TableField(value = "name", updateStrategy=FieldStrategy.IGNORED)
private String name;

3、使用UpdateWrapper更新(当属性很多写起来很麻烦)

通过baseMapper的UpdateWrapper将实体类的指定字段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);
        // 根据id更新所有数据
        methodList.add(new UpdateWithNullMethod());
        return methodList;
    }

}

(2)、方法对应的实现类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);
        // 第三个参数必须和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();

        // 默认: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) {
            // 不进行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)、自定义基础Mapper继承BaseMapper

import com.baomidou.mybatisplus.core.mapper.BaseMapper;

/**
 * @description: 自定义mapper借口,mybatisPlus
 * @author: zzt
 */
public interface MyBaseMapper<T> extends BaseMapper<T> {

    /**
     * 全字段更新,更新为null的字段
     * @param obj 待更新对象
     * @return 是否成功
     */
    boolean updateWithNull(T obj);
}

最后直接调用即可。

到此这篇关于MybatisPlus更新为null的字段及自定义sql注入的文章就介绍到这了,更多相关MybatisPlus更新为null内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Springboot启动流程详细分析

    Springboot启动流程详细分析

    这篇文章主要介绍了SpringBoot启动过程的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-12-12
  • MyBatis中使用分页插件PageHelper实现分页功能

    MyBatis中使用分页插件PageHelper实现分页功能

    分页是经常使用的功能,本文主要介绍了Mybatis中处理特殊SQL处理逻辑,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-06-06
  • Java私有构造函数作用原理解析

    Java私有构造函数作用原理解析

    这篇文章主要介绍了Java私有构造函数作用原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • Spring依赖注入中的@Resource与@Autowired详解

    Spring依赖注入中的@Resource与@Autowired详解

    这篇文章主要介绍了Spring依赖注入中的@Resource与@Autowired详解,提到Spring依赖注入,大家最先想到应该是@Resource和@Autowired,对于Spring为什么要支持两个这么类似的注解却未提到,属于知其然而不知其所以然,本文就来做详细讲解,需要的朋友可以参考下
    2023-09-09
  • springMVC之HandlerExceptionResolver使用

    springMVC之HandlerExceptionResolver使用

    这篇文章主要介绍了springMVC之HandlerExceptionResolver使用,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • Java实现经典游戏打砖块游戏的示例代码

    Java实现经典游戏打砖块游戏的示例代码

    这篇文章主要介绍了如何利用Java实现经典的游戏—打砖块。玩家操作一根萤幕上水平的“棒子”,让一颗不断弹来弹去的“球”在撞击作为过关目标消去的“砖块”的途中不会落到萤幕底下。感兴趣的小伙伴可以了解一下
    2022-02-02
  • Java设计模式之桥接模式详解

    Java设计模式之桥接模式详解

    桥接模式(Bridge Pattern)是一种结构型设计模式,用于将抽象部分和实现部分`分离开来,从而使它们可以独立地进行变化,本节给大家讲一下设计模式中的桥接模式,并结合实际业务场景给大家讲解如何使用,需要的朋友可以参考下
    2023-07-07
  • Idea创建Jsp项目完整版教程

    Idea创建Jsp项目完整版教程

    一直在使用eclipse,对idea嗤之以鼻,前些日子换成了idea以后觉得太香了,这篇文章主要给大家介绍了关于Idea创建Jsp项目的相关资料,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2024-04-04
  • MyBatis使用注解开发实现步骤解析

    MyBatis使用注解开发实现步骤解析

    这篇文章主要介绍了MyBatis使用注解开发实现步骤解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08
  • JWT整合Springboot的方法步骤

    JWT整合Springboot的方法步骤

    本文主要介绍了JWT整合Springboot的方法步骤,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11

最新评论