MyBatis Plus 遇到的坑,update只能全量更新所有字段,无法实现只更新部分字段
创始人
2025-05-28 20:02:13

目录

    • 一、BaseMapper.update(entity, updateWrapper) 入参说明
    • 二、踩坑代码
      • 1. t_user.sql
      • 2. TUserMapper.java
      • 3. TUserMapper.java
      • 4. TUserMapper.xml
      • 5. SQL 执行日志
      • 6. 报错信息
      • 7. 报错分析
      • 8. 解决方案

一、BaseMapper.update(entity, updateWrapper) 入参说明

首先,我们先来看下 BaseMapper 中 update(entity, updateWrapper) 的方法签名:

/*** 根据 whereEntity 条件,更新记录** @param entity        实体对象* @param updateWrapper 实体对象封装操作类*/
int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper updateWrapper);

参数说明如下:

  • T entity 入参:用于传入 update 时需要 set 的值。

    可以为 null,为 null 时通过 updateWrapper 指定 set 值;

  • Wrapper updateWrapper 入参:主要用于传入 update 时需要的 where 值,也可以指定需要 set 的值。

    可以为 null,为 null 时更新全表。

二、踩坑代码

1. t_user.sql

CREATE TABLE `t_user` (`id` BIGINT(16) NOT NULL AUTO_INCREMENT COMMENT '主键',`username` VARCHAR(64) NOT NULL COMMENT '用户名' COLLATE 'utf8_general_ci',`password` VARCHAR(64) NOT NULL COMMENT '密码' COLLATE 'utf8_general_ci',`age` INT(8) NULL DEFAULT NULL COMMENT '年龄',`salary` INT(8) NULL DEFAULT NULL COMMENT '工资',`create_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`update_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',PRIMARY KEY (`id`) USING BTREE
)
COMMENT='用户表'
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;

2. TUserMapper.java

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.demo.module.entity.TUser;
import com.demo.module.mapper.TUserMapper;
import com.demo.module.service.TUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;/*** 用户表 服务实现类** @author ACGkaka* @since 2021-04-25*/
@Service
public class TUserServiceImpl extends ServiceImpl implements TUserService {@Autowiredprivate TUserMapper userMapper;@Overridepublic void updateUser(String username) {UpdateWrapper updateWrapper = new UpdateWrapper<>();updateWrapper.lambda().set(TUser::getUsername, username).eq(TUser::getId, 7);userMapper.update(null, updateWrapper);}
}

3. TUserMapper.java

import com.demo.module.entity.TUser;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;/*** 用户表 Mapper 接口** @author ACGkaka* @since 2021-04-25*/
@Mapper
public interface TUserMapper extends BaseMapper {int update(TUser user);
}

4. TUserMapper.xml



UPDATE t_userSET username = #{username},password = #{password},create_time = #{createTime},update_time = #{updateTime}WHERE id = #{id}

5. SQL 执行日志

Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3946f66d] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@378b61ea] will not be managed by Spring
==>  Preparing: UPDATE t_user SET username = ?, password = ?, create_time = ?, update_time = ? WHERE id = ?
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3946f66d]

6. 报错信息

控制台报错:org.apache.ibatis.binding.BindingException: Parameter 'username' not found. Available parameters are [ew, param1, et, param2]

详细报错日志如下:

2023-03-16 10:37:59.493 ERROR 29760 --- [nio-8081-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.binding.BindingException: Parameter 'username' not found. Available parameters are [ew, param1, et, param2]] with root causeorg.apache.ibatis.binding.BindingException: Parameter 'username' not found. Available parameters are [ew, param1, et, param2]at org.apache.ibatis.binding.MapperMethod$ParamMap.get(MapperMethod.java:212) ~[mybatis-3.5.6.jar:3.5.6]at org.apache.ibatis.reflection.wrapper.MapWrapper.get(MapWrapper.java:45) ~[mybatis-3.5.6.jar:3.5.6]at org.apache.ibatis.reflection.MetaObject.getValue(MetaObject.java:122) ~[mybatis-3.5.6.jar:3.5.6]at com.baomidou.mybatisplus.core.MybatisParameterHandler.setParameters(MybatisParameterHandler.java:205) ~[mybatis-plus-core-3.4.1.jar:3.4.1]at org.apache.ibatis.executor.statement.PreparedStatementHandler.parameterize(PreparedStatementHandler.java:94) ~[mybatis-3.5.6.jar:3.5.6]at org.apache.ibatis.executor.statement.RoutingStatementHandler.parameterize(RoutingStatementHandler.java:64) ~[mybatis-3.5.6.jar:3.5.6]at com.baomidou.mybatisplus.core.executor.MybatisSimpleExecutor.prepareStatement(MybatisSimpleExecutor.java:99) ~[mybatis-plus-core-3.4.1.jar:3.4.1]at com.baomidou.mybatisplus.core.executor.MybatisSimpleExecutor.doUpdate(MybatisSimpleExecutor.java:55) ~[mybatis-plus-core-3.4.1.jar:3.4.1]at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117) ~[mybatis-3.5.6.jar:3.5.6]at com.baomidou.mybatisplus.core.executor.MybatisCachingExecutor.update(MybatisCachingExecutor.java:85) ~[mybatis-plus-core-3.4.1.jar:3.4.1]at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:197) ~[mybatis-3.5.6.jar:3.5.6]at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_60]at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_60]at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_60]at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_60]at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:426) ~[mybatis-spring-2.0.5.jar:2.0.5]at com.sun.proxy.$Proxy56.update(Unknown Source) ~[na:na]at org.mybatis.spring.SqlSessionTemplate.update(SqlSessionTemplate.java:287) ~[mybatis-spring-2.0.5.jar:2.0.5]at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.execute(MybatisMapperMethod.java:65) ~[mybatis-plus-core-3.4.1.jar:3.4.1]at com.baomidou.mybatisplus.core.override.MybatisMapperProxy$PlainMethodInvoker.invoke(MybatisMapperProxy.java:148) ~[mybatis-plus-core-3.4.1.jar:3.4.1]at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:89) ~[mybatis-plus-core-3.4.1.jar:3.4.1]at com.sun.proxy.$Proxy57.update(Unknown Source) ~[na:na]at com.demo.module.service.impl.TUserServiceImpl.updateUser(TUserServiceImpl.java:29) ~[classes/:na]at com.demo.module.service.impl.TUserServiceImpl$$FastClassBySpringCGLIB$$361c0747.invoke() ~[classes/:na]at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.6.jar:5.3.6]at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) ~[spring-aop-5.3.6.jar:5.3.6]at com.demo.module.service.impl.TUserServiceImpl$$EnhancerBySpringCGLIB$$32d6ea41.updateUser() ~[classes/:na]at com.demo.module.controller.TUserController.update(TUserController.java:39) ~[classes/:na]at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_60]at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_60]at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_60]at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_60]at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197) ~[spring-web-5.3.6.jar:5.3.6]at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141) ~[spring-web-5.3.6.jar:5.3.6]at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.3.6.jar:5.3.6]at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894) ~[spring-webmvc-5.3.6.jar:5.3.6]at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.6.jar:5.3.6]at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.6.jar:5.3.6]at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1060) ~[spring-webmvc-5.3.6.jar:5.3.6]at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:962) ~[spring-webmvc-5.3.6.jar:5.3.6]at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.6.jar:5.3.6]at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.6.jar:5.3.6]at javax.servlet.http.HttpServlet.service(HttpServlet.java:626) ~[tomcat-embed-core-9.0.45.jar:4.0.FR]at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.6.jar:5.3.6]at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.45.jar:4.0.FR]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.45.jar:9.0.45]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.45.jar:9.0.45]at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.45.jar:9.0.45]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.45.jar:9.0.45]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.45.jar:9.0.45]at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.6.jar:5.3.6]at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.6.jar:5.3.6]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.45.jar:9.0.45]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.45.jar:9.0.45]at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.6.jar:5.3.6]at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.6.jar:5.3.6]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.45.jar:9.0.45]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.45.jar:9.0.45]at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.6.jar:5.3.6]at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.6.jar:5.3.6]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.45.jar:9.0.45]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.45.jar:9.0.45]at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.45.jar:9.0.45]at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) [tomcat-embed-core-9.0.45.jar:9.0.45]at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) [tomcat-embed-core-9.0.45.jar:9.0.45]at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) [tomcat-embed-core-9.0.45.jar:9.0.45]at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.45.jar:9.0.45]at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) [tomcat-embed-core-9.0.45.jar:9.0.45]at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357) [tomcat-embed-core-9.0.45.jar:9.0.45]at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) [tomcat-embed-core-9.0.45.jar:9.0.45]at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.45.jar:9.0.45]at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893) [tomcat-embed-core-9.0.45.jar:9.0.45]at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1707) [tomcat-embed-core-9.0.45.jar:9.0.45]at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.45.jar:9.0.45]at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_60]at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_60]at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.45.jar:9.0.45]at java.lang.Thread.run(Thread.java:745) [na:1.8.0_60]

7. 报错分析

结合 4.SQL 执行日志5.报错信息,我们可以发现是因为我们在调用 userMapper.update() 方法更新的时候,只指定了更新 username 字段,但是 SQL 中却 setpassword 字段,我们没有指定 password 字段要更新的值,所以报错了。

为什么我只指定了更新 username 字段,但是却更新了所有字段呢?

推测 MyBatis Plus 框架应该是使用了 模板模式 来实现了 BaseMapper.update() 方法,当我们在自己的 Mapper 中继承了 BaseMapper,又自己实现了 update() 方法的时候,BaseMapper 中原生的 update() 方法就不会生效。

8. 解决方案

有两种方式来解决这个问题:

方法一: 删除 TUserMapper.java 中的 update() 方法,改为统一使用 MyBatis Plus 提供的默认实现方式。

方法二: 继续使用 TUserMapper.java 中的 update() 方法,但是需要在 TUserMapper.xml 中通过 标签来支持只更新部分字段。

整理完毕,完结撒花~ 🌻

相关内容

热门资讯

玩腻精致露营的北漂跑郊区冰面上... 今冬的冰雪奇缘开始走小众新奇赛道。 “冰鲜小龙虾”在全国各大湖泊里扎堆出现,这是北欧同款冰浮 深圳人...
2026“巴蜀文化旅游走廊”主... 2月12日,2026“巴蜀文化旅游走廊”主题列车项目启动仪式在重庆北站北广场举行。活动由重庆市文旅委...
观鸥赏花品滇菜 春城昆明调至“... 昆明信息港讯 记者周智宇2月13日,2026“来昆明过大年观鸥赏花品滇菜”系列活动发布会在昆明南屏步...
昆明发布新春文旅系列活动 邀游... 央广网昆明2月13日消息(记者 魏文青)2月13日,昆明市文化和旅游局、市园林绿化局、市商务局在南屏...