MyBatis Plus更新对象无法设空值解决方案

原因

因为 MyBatis-Plus 自带的更新方法,都有对对象空值进行判空。只有不为空的字段才会进行数据更新。

解决方式

在实体类对应的字段上加注解@TableField(strategy=FieldStrategy.IGNORED),忽略null值的判断,例如:

@TableField(updateStrategy = FieldStrategy.IGNORED)
private String address;

示例:

1、未加注解(无法设入空值,见代码结果):

//实体private String address;
@Test
public void updateUserTest(){
  User user = new User();
  user.setId(1);
  user.setState((byte) 1);
  user.setAddress(null);
  userService.updateById(user);
}
​
//结果
==> Preparing: UPDATE user SET state=? WHERE id=?
==> Parameters: 1(Byte), 1(Integer)
​

2、加注解(可以设入空值,看代码结果)

//实体@TableField(updateStrategy = FieldStrategy.IGNORED)
private String address;
@Test
public void updateUserTest(){
  User user = new User();
  user.setId(1);
  user.setState((byte) 1);
  user.setAddress(null);
  userService.updateById(user);
}
​
//结果
==> Preparing: UPDATE user SET address=?, state=? WHERE id=?
==> Parameters: null, 1(Byte), 1(Integer)

3、直接使用 UpdateWrapper

@Test
public void updateUserTest(){
  UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
  userUpdateWrapper.set("address", null);
  userUpdateWrapper.lambda().eq(User::getId, 1);
  userService.update(userUpdateWrapper);
}
​
//结果
==> Preparing: UPDATE user SET address=? WHERE (id = ?)
==> Parameters: null, 1(Integer)

附上 MyBatis-Plus 表字段标识 注解类

/**
 * 表字段标识
 *
 * @author hubin sjy tantan
 * @since 2016-09-09
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface TableField {
​
  /**
   * 字段值(驼峰命名方式,该值可无)
   */
  String value() default "";
​
  /**
   * 是否为数据库表字段
   * 默认 true 存在,false 不存在
   */
  boolean exist() default true;
​
  /**
   * 字段 where 实体查询比较条件
   * 默认 `=` 等值
   */
  String condition() default "";
​
  /**
   * 字段 update set 部分注入, 该注解优于 el 注解使用
   * <p>
   * 例1:@TableField(.. , update="%s+1") 其中 %s 会填充为字段
   * 输出 SQL 为:update 表 set 字段=字段+1 where ...
   * <p>
   * 例2:@TableField(.. , update="now()") 使用数据库时间
   * 输出 SQL 为:update 表 set 字段=now() where ...
   */
  String update() default "";
​
  /**
   * 字段验证策略之 insert: 当insert操作时,该字段拼接insert语句时的策略
   * IGNORED: 直接拼接 insert into table_a(column) values (#{columnProperty});
   * NOT_NULL: insert into table_a(<if test="columnProperty != null">column</if>) values (<if test="columnProperty != null">#{columnProperty}</if>)
   * NOT_EMPTY: insert into table_a(<if test="columnProperty != null and columnProperty!=''">column</if>) values (<if test="columnProperty != null and columnProperty!=''">#{columnProperty}</if>)
   *
   * @since 3.1.2
   */
  FieldStrategy insertStrategy() default FieldStrategy.DEFAULT;
​
  /**
   * 字段验证策略之 update: 当更新操作时,该字段拼接set语句时的策略
   * IGNORED: 直接拼接 update table_a set column=#{columnProperty}, 属性为null/空string都会被set进去
   * NOT_NULL: update table_a set <if test="columnProperty != null">column=#{columnProperty}</if>
   * NOT_EMPTY: update table_a set <if test="columnProperty != null and columnProperty!=''">column=#{columnProperty}</if>
   *
   * @since 3.1.2
   */
  FieldStrategy updateStrategy() default FieldStrategy.DEFAULT;
​
  /**
   * 字段验证策略之 where: 表示该字段在拼接where条件时的策略
   * IGNORED: 直接拼接 column=#{columnProperty}
   * NOT_NULL: <if test="columnProperty != null">column=#{columnProperty}</if>
   * NOT_EMPTY: <if test="columnProperty != null and columnProperty!=''">column=#{columnProperty}</if>
   *
   * @since 3.1.2
   */
  FieldStrategy whereStrategy() default FieldStrategy.DEFAULT;
​
  /**
   * 字段自动填充策略
   */
  FieldFill fill() default FieldFill.DEFAULT;
​
  /**
   * 是否进行 select 查询
   * <p>大字段可设置为 false 不加入 select 查询范围</p>
   */
  boolean select() default true;
​
  /**
   * 是否保持使用全局的 Format 的值
   * <p> 只生效于 既设置了全局的 Format 也设置了上面 {@link #value()} 的值 </p>
   * <li> 如果是 false , 全局的 Format 不生效 </li>
   *
   * @since 3.1.1
   */
  boolean keepGlobalFormat() default false;
​
  /**
   * JDBC类型 (该默认值不代表会按照该值生效)
   * <p>
   * {@link ResultMapping#jdbcType} and {@link ParameterMapping#jdbcType}
   *
   * @since 3.1.2
   */
  JdbcType jdbcType() default JdbcType.UNDEFINED;
​
  /**
   * 类型处理器 (该默认值不代表会按照该值生效)
   * <p>
   * {@link ResultMapping#typeHandler} and {@link ParameterMapping#typeHandler}
   *
   * @since 3.1.2
   */
  Class<? extends TypeHandler> typeHandler() default UnknownTypeHandler.class;
​
  /**
   * 指定小数点后保留的位数
   * <p>
   * {@link ParameterMapping#numericScale}
   *
   * @since 3.1.2
   */
  String numericScale() default "";
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Springboot+MybatisPlus+Oracle实现主键自增的示例代码

    上周周一,本来刚过完周末,高高兴兴,老大突然安排了个活,要在一天内把项目的MySQL数据库换成Oracle数据库,我们都知道这是不可能完成的任务,但是,秉承着"没有困难的工作,只有不努力的打工人"的精神,我们马上投入了工作,第一步当然是先配置数据库.oracle建表,这个解决调试了一上午,然后下午卡到oracle主键了,所有人网上找方法,一直到第二天凌晨3点半都还没解决,网上方法很多,试了好多都不管用,终于第二天才找到了满足的方法. 废话不多说,下面贴出. application.ym

  • mybatisPlus自定义批量新增的实现代码

    mybatisPlus底层的新增方法是一条一条的新增的,今天自定义批量新增方法. 创建自定义数据方法注入类 /** * @Description: EasySqlInjector 自定义数据方法注入 * @Author WangYejian * @Date: 2020/11/4 14:34 */ public class EasySqlInjector extends DefaultSqlInjector { @Override public List<AbstractMethod> getM

  • Mybatis Plus插件三种方式的逆向工程的使用

    本文源码:GitHub·点这里 || GitEE·点这里 一.逆向工程简介 在Java开发中,持久层最常用的框架就是mybatis,该框架需要编写sql语句,mybatis官方提供逆向工程,可以把数据表自动生成执行所需要的基础代码,例如:mapper接口,sql映射文件,pojo实体类等,避免基础代码维护的繁杂过程. 在实际的使用中,常用的逆向工程方式如上,mybatis框架,mybatis-plus框架,插件方式. 二.Mybatis方式 1.基础描述 基于xml配置的方式,生成mybatis

  • MyBatis-Plus实现多数据源的示例代码

    多数据源的目的在于一个代码模块可调用多个数据库的数据进行某些业务操作. MyBatis-Plus开发者写了一个多数据源叫dynamic-datasource-spring-boot-starter,非常简单易用. dynamic-datasource-spring-boot-starter文档 官方文档部分截图: 第三方集成的,基本上是目前比较主流的(用的比较多). 一.添加Maven依赖 <dependency> <groupId>com.baomidou</groupId

  • mybatis-plus  mapper中foreach循环操作代码详解(新增或修改)

    .循环添加 接口处: 分别是 void 无返回类型 :有的话是(resultType)返回类型,参数类型(parameterType) list , 如: 在mapper文件中分别对应ID,参数类型和返回类型. 循环处理,如下: <insert id="insertPack" parameterType="java.util.List"> insert into t_ev_bu_pack ( PACK_CODE, BIN, PACK_PROD_TIME,

  • Mybatisplus主键生成策略算法解析

    mybatisplus支持多种主键生成策略,默认采用认 ID_WORKER 即雪花算法 雪花算法 snowflflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID.其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0.可以保证几乎全球唯一! mybatisplus默认主键生成策略有可能会和我们的数据库

  • mybatis-plus3.4.0逻辑删除报错的解决

    特别注意!!! 无论数据库字段,实体类字段,还是平时取其它字段名字时候,或者方法这些名字,一定不能和关键字重名,因为这样可能出现一些让人无法看出的错误 在进行mybatis-plus逻辑删除字段时候,我在数据库定义了delete字段定义为int类型,默认值是0,然后又在实体类中定义了这个字段delete并且在实体类的这个字段上面添加了注解@TableLogic,并且在application.properties中开启.(我使用的是3.4.0) 根据官方文档,在3.4.0版本中只需要以上两个步骤即

  • SpringBoot中引入MyBatisPlus的常规操作

    一.前言 近来参与一个电力大数据项目,开发小组决定在 DAO 层使用 MyBatisPlus --国产.新颖.强大.轻量. 官方API地址:http://mp.baomidou.com/#/?id=%E7%AE%80%E4%BB%8B 二.通用 CRUD 通过本项目(表少,数据量大,非常适合) 发现 MyBatisPlus 在 单表CRUD 方面 比原来的的 MyBatis 的有着绝对优势: VS PS MyBatis MyBatisPlus 代码生成器 数据库有些表的字段发声改变 ① 再次运行

  • 解决Mybatis-plus找不到对应表及默认表名命名规则的问题

    错误截图 在测试使用Mybatis-plus查询数据库时报错 报错信息大概意思时在数据库中没有user这张表 而实际上确实没有 尝试 我这里application.ymml没有与Mybatis-plus的相关配置 为探究在没有配置的情况下时Mybatis-plus默认时按照什么来定义表名的 猜想有两个地方有可能(因为只有这两个地方是user) 先测试第一个 可以看到和之前的错误一样没有效果 测试第二个点 虽然报错,但是证明了在没有配置表名的情况下mybatis-plus是默认按照实体类名去查询数

  • Mybatis plus的自动填充与乐观锁的实例详解(springboot)

    自动填充 项目中经常会遇到一些数据,每次都使用相同的方式填充,如插入时间.更新时间.Mybatis-plus的自动填充功能可以帮助我们快速实现. 1.表中加入create_time,update_time字段 2.实体类注解填充字段 @TableField(fill= FieldFill.INSERT) private Date createTime; @TableField(fill = FieldFill.INSERT_UPDATE) private Date updateTime; /**

随机推荐