mybatis一个非典型使用异常

本文探讨了MyBatis框架中出现的参数传递异常,具体表现为找不到指定参数'custId'的问题。通过分析异常堆栈,明确了错误原因在于mapper接口与XML配置文件之间的参数不匹配,并给出了相应的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

mybatis传参有多种方式,这里捕获一种异常如下

org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.binding.BindingException: Parameter 'custId' not found. Available parameters are [arg1, arg0, param1, param2]
	at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:77)
	at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:446)
	at com.sun.proxy.$Proxy131.selectOne(Unknown Source)
	at org.mybatis.spring.SqlSessionTemplate.selectOne(SqlSessionTemplate.java:166)
	at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:83)
	at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:59)
	at com.sun.proxy.$Proxy132.getCustomerBankAccountByCustIdAndBankAccountNum(Unknown Source)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:197)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
	at com.sun.proxy.$Proxy134.getCustomerBankAccountByCustIdAndBankAccountNum(Unknown Source)
	at com.sinochem.goldgoods.customer.service.impl.CustomerBankAccountServiceImpl.getCustomerBankAccountByCustIdAndBankAccountNum(CustomerBankAccountServiceImpl.java:160)
	at com.sinochem.goldgoods.account.service.impl.AccountRemoteServiceImpl.getCustomerBankAccountByCustIdAndBankAccountNum(AccountRemoteServiceImpl.java:421)
	at com.sinochem.goldgoods.cps.account.impl.AccountCpsServiceImpl.getCustomerBankAccountInfo(AccountCpsServiceImpl.java:2108)
	at com.sinochem.goldgoods.gateway.api.account.AccountApi.getCustomerBankAccountInfo(AccountApi.java:212)
	at com.sinochem.goldgoods.gateway.api.account.AccountApi$$FastClassBySpringCGLIB$$6a056101.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:684)
	at com.sinochem.goldgoods.gateway.api.account.AccountApi$$EnhancerBySpringCGLIB$$8f62e92f.getCustomerBankAccountInfo(<generated>)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974)
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:877)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at com.sinochem.goldgoods.system.security.JwtAuthenticationTokenFilter.doFilterInternal(JwtAuthenticationTokenFilter.java:153)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:158)
	at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:126)
	at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:111)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:84)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320)
	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127)
	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at com.sinochem.goldgoods.system.security.JwtAuthenticationTokenFilter.doFilterInternal(JwtAuthenticationTokenFilter.java:153)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:66)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)
	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357)
	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:109)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:496)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1468)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)
Caused by: org.apache.ibatis.binding.BindingException: Parameter 'custId' not found. Available parameters are [arg1, arg0, param1, param2]
	at org.apache.ibatis.binding.MapperMethod$ParamMap.get(MapperMethod.java:204)
	at org.apache.ibatis.reflection.wrapper.MapWrapper.get(MapWrapper.java:45)
	at org.apache.ibatis.reflection.MetaObject.getValue(MetaObject.java:122)
	at org.apache.ibatis.executor.BaseExecutor.createCacheKey(BaseExecutor.java:219)
	at org.apache.ibatis.executor.CachingExecutor.createCacheKey(CachingExecutor.java:146)
	at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:82)
	at sun.reflect.GeneratedMethodAccessor167.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.apache.ibatis.plugin.Invocation.proceed(Invocation.java:49)
	at com.github.pagehelper.SqlUtil._processPage(SqlUtil.java:401)
	at com.github.pagehelper.SqlUtil.processPage(SqlUtil.java:374)
	at com.github.pagehelper.PageHelper.intercept(PageHelper.java:250)
	at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:61)
	at com.sun.proxy.$Proxy273.query(Unknown Source)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:148)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:141)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:77)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:433)
	... 128 common frames omitted

这种错误是因为传参的mapper跟配置文件不匹配造成的,parameterType如果是包装类,就可以在条件中使用类的属性,如果使用@Param("XXX"),则mapper配置文件或注解中可以使用比较复杂的数据结构。

<think>嗯,用户问的是MyBatis中updateById的使用注意事项。我需要先回忆一下MyBatis的基础知识,特别是关于更新操作的部分。首先,updateById通常不是MyBatis自带的,而是MyBatis Plus中的方法,对吧?所以可能用户混淆了MyBatisMyBatis Plus。这点需要明确说明,避免用户误解。 接下来,用户可能想知道在使用类似updateById这样的方法时需要注意什么。首先,要确保主键正确,因为根据ID更新,如果主键字段不对或者值错误,会导致更新失败或者影响错误的数据。另外,字段是否为null的问题,比如如果实体类中有null字段,是否会被更新到数据库,这取决于框架的配置,比如MyBatis Plus的全局策略或者字段注解。 然后,乐观锁的问题。如果用户的项目中使用了乐观锁,比如有@Version注解的字段,updateById会自动处理版本号,这时候需要确保实体类中的版本号是正确的,否则可能会更新失败。这一点很重要,容易被忽略。 还有SQL注入的风险,虽然MyBatis Plus生成的SQL一般参数化,但用户如果自定义了update语句,需要注意避免拼接字符串,防止注入攻击。此外,批量操作时的性能问题,频繁的单条更新会影响效率,应该考虑批量更新方法。 另外,数据库权限问题,用户是否有执行update的权限,这也是一个潜在的问题点。事务管理方面,确保在需要事务的方法上添加注解,保证数据一致性。最后,日志和错误排查,开启SQL日志可以帮助调试。 不过,用户提到的是updateById,可能需要具体到MyBatis的实现,比如自己写的update语句,这时候注意事项可能有所不同,比如动态SQL的编写,确保非空字段的判断,参数的正确传递等。但根据常见情况,用户可能指的是MyBatis Plus的updateById,所以应该以这个为前提来回答。 总结下来,注意事项大概包括:确认主键、非null字段处理、乐观锁、SQL注入、批量操作、权限、事务、日志等。需要分点说明,结构清晰,每个点详细解释原因和解决方法。同时提醒用户注意MyBatisMyBatis Plus的区别,避免混淆。可能还需要提到实体类映射是否正确,比如字段名和数据库列名是否对应,使用@TableId注解等。 最后,检查是否有遗漏点,比如触发器和数据库约束是否会影响更新结果,或者并发更新时的锁问题,但乐观锁已经覆盖了部分。还有,空值更新是否需要动态SQL,比如使用<if>标签来判断字段是否为null,避免覆盖数据库中的现有值。这点在MyBatis的XML配置中常见,需要根据业务需求决定是否更新null值。</think>以下是在MyBatis(及MyBatis Plus扩展)中使用`updateById`方法时需要注意的关键事项,按问题场景分类说明: --- ### 一、明确框架差异 1. **MyBatis原生 vs MyBatis Plus** - `updateById`是**MyBatis Plus**提供的扩展方法(需继承`BaseMapper<T>`),MyBatis原生无此方法。 - 若使用原生MyBatis,需手动编写XML映射文件或注解SQL。 --- ### 二、主键字段准确性 1. **标识主键字段** - 确保实体类主键字段用`@TableId`标注(MyBatis Plus),或XML中正确配置`<id>`。 - 错误示例:未标注主键导致更新条件错误。 ```java @TableId(value = "id", type = IdType.AUTO) // 明确主键映射 private Long id; ``` 2. **主键值有效性** - 传入实体的主键值必须非空且存在,否则可能: - 更新0条数据(无对应ID) - 因空主键抛出异常 --- ### 三、字段更新策略 1. **非空字段处理** - MyBatis Plus默认更新策略为`NOT_NULL`:**仅更新非空字段**。 - 若需强制更新字段为`null`,需: - 设置全局策略:`mybatis-plus.global-config.db-config.update-strategy=ignored` - 使用`@TableField(updateStrategy = FieldStrategy.IGNORED)`注解特定字段 2. **动态SQL控制** - 原生MyBatis中需在XML中用`<if>`手动控制更新条件: ```xml <update id="updateUser"> UPDATE user <set> <if test="name != null">name = #{name},</if> <if test="age != null">age = #{age},</if> </set> WHERE id = #{id} </update> ``` --- ### 四、并发与锁机制 1. **乐观锁配置** - 使用`@Version`注解实现乐观锁: ```java @Version private Integer version; // 更新时自动+1 ``` - 需确保数据库中存在`version`字段,更新失败会抛出`OptimisticLockException` --- ### 五、性能与批量操作 1. **避免单条循环更新** - 频繁调用`updateById`影响性能,改用`updateBatchById`批量更新(MyBatis Plus) ```java List<User> userList = ...; userService.updateBatchById(userList); // 批量执行 ``` --- ### 六、安全与事务 1. **SQL注入防范** - 避免在自定义XML中使用`${}`拼接参数,坚持用`#{}` ```xml <!-- 危险写法 --> WHERE id = ${id} <!-- 正确写法 --> WHERE id = #{id} ``` 2. **事务边界控制** - 在Service层添加`@Transactional`注解保证原子性: ```java @Transactional public void updateUser(User user) { userMapper.updateById(user); // 其他数据库操作 } ``` --- ### 七、调试与监控 1. **启用SQL日志** - 配置`application.yml`输出完整SQL: ```yaml mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl ``` --- ### 典型错误场景 - **场景1**:实体类字段为`null`未被更新 **解决**:调整字段更新策略或检查数据赋值逻辑。 - **场景2**:更新后版本号未自增 **解决**:检查`@Version`字段是否被其他代码修改。 - **场景3**:更新影响行数为0 **解决**:检查主键值是否存在,或乐观锁版本是否匹配。 --- 通过以上要点控制,可有效规避`updateById`的常见问题,建议结合单元测试验证关键业务场景的更新逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值