Mybatis-plus更新null字段问题分析与解决方案
起因:更新字段为Null的常见需求 在项目开发中,有时需要将Oracle数据库中的特定字段值更新为Null。这看似是一个简单的操作,但在使用MyBatis-Plus框架时,却可能遇到意想不到的阻碍。 遇到问题后,通常首先会搜索解决方案。网上相关的讨论很多,提供的方法也类似。但经过逐一尝试,发现这些方
起因:更新字段为Null的常见需求
在项目开发中,有时需要将Oracle数据库中的特定字段值更新为Null。这看似是一个简单的操作,但在使用MyBatis-Plus框架时,却可能遇到意想不到的阻碍。

遇到问题后,通常首先会搜索解决方案。网上相关的讨论很多,提供的方法也类似。但经过逐一尝试,发现这些方法要么解释不够深入,要么不适用于特定的场景,未能从根本上解决问题。
常见解决方案为何失效
首先排除全局配置的方案。因为通常只需要对单个表的特定字段进行Null值更新,其他字段仍需保持非空检查,全局修改并不合适。
于是,注意力转向第二种方案:在需要更新为Null的字段上添加注解 @TableField(strategy = FieldStrategy.IGNORED)。这个思路是正确的,因为MyBatis-Plus默认会对字段进行非空判断,而IGNORED策略可以忽略这个判断。通过查看源码可以明确这一点:
//字段策略枚举类
public enum FieldStrategy {
IGNORED(0, "忽略判断"),
NOT_NULL(1, "非 NULL 判断"),
NOT_EMPTY(2, "非空判断");
//省略部分代码
}
因此,正确的配置方式如下:
@TableField(value = "BIRTHDAY", strategy = FieldStrategy.IGNORED) private Date birthday;
需要说明的是,全局配置本质上也是修改这个枚举的默认值。但为了一个字段而改变全局规则,并不是一个理想的选择。
然而,问题恰恰出现在这里。按照大多数教程的指引,配置到这一步似乎就应该成功了。但实际运行时,程序仍然会报错。错误提示往往指向ja vaType的类型为other。查阅源码后确认,该属性的默认值确实是other。
突破瓶颈:找到有效解决方案
配置FieldStrategy.IGNORED后仍然报错,说明问题需要更深层次的解决。关键在于如何正确配置ja vaType。
针对此问题,网上另一种方案是放弃MyBatis-Plus的便捷功能,转而编写原始的XML SQL语句,在SQL中通过#{property, jdbcType=XXX}来指定类型。例如:
insert into cost values( cost_seq.nextval, #{name,jdbcType=VARCHAR}, #{base_duration,jdbcType=INTEGER}, #{base_cost,jdbcType=DOUBLE} )
这种方法理论上可行,但并未采用。原因在于,选择MyBatis-Plus正是为了避免编写繁琐的SQL语句。如果为了解决Null更新问题而重写SQL,就背离了使用框架的初衷。而且,直接编写SQL根本不会触发之前的错误。
那么,是否存在一种方法,既能享受MyBatis-Plus的便利,又能完美解决Null更新问题?答案是肯定的。
实际上,MyBatis-Plus的@TableField注解支持一个强大的el属性(Expression Language)。通过它,可以直接指定jdbcType。源码的注释中已经给出了提示:
/**
*
* 当该Field为类对象时, 可使用#{对象.属性}来映射到数据表.
*
*
* 支持:@TableField(el = "role, jdbcType=BIGINT)
* 支持:@TableField(el = "role, typeHandler=com.baomidou.springcloud.typehandler.PhoneTypeHandler")
*
*/
String el() default "";
如果觉得抽象,可以直接参考最终的配置方式。
最终配置方式一:注解指定
在字段注解中,同时指定strategy和el属性:
/** 检验结果单位(码值:lab_result_unit)*/ @TableField(value="lab_result_unit", strategy = FieldStrategy.IGNORED, el = "labResultUnit,jdbcType=DECIMAL") private Integer labResultUnit;
这样配置后,MyBatis-Plus在生成SQL时,会忽略该字段的非空判断,并为其赋予正确的DECIMAL jdbcType,从而允许Null值被顺利更新到数据库。
最终配置方式二:全局配置(备选)
如果多个字段需要类似处理,或者倾向于全局配置,也可以在application.yml中进行设置:
mybatis-plus:
configuration:
jdbc-type-for-null: 'null' #注意:单引号是必须的
这个配置会让MyBatis-Plus对所有Null参数都使用JDBC的NULL类型,这也是一种解决方案。但请注意,这会影响全局,需要根据项目实际情况进行权衡。
回顾整个过程,网上很多文章提供的解决方案在特定环境下可能有效,但软件开发中很少存在“一招鲜吃遍天”的情况。更多时候,需要像这样层层剖析,结合框架源码和自身业务场景,才能找到真正适合自己的解决路径。
总结
解决MyBatis-Plus更新Null字段的问题,核心在于两点:一是通过FieldStrategy.IGNORED绕过字段的非空更新策略;二是在某些数据库驱动(如Oracle)下,需要通过el属性或全局配置明确指定Null值的jdbcType,以避免类型映射错误。希望这个具体的排查和解决过程,能为遇到类似问题时提供一个清晰的参考。
