Closed songxiaoxiao closed 2 years ago
当前使用版本(必填,否则不予处理)
3.4.3
该问题是如何引起的?(确定最新版也有问题再提!!!)
系统配置 mybatis-plus: global-config: db-config: update-strategy: not_null lambdaUpdate().eq(Entity::id, 17834).set(Entity::status, null).set(...); 并没有过滤掉为空的set
重现步骤(如果有就写完整)
报错信息
Cause: java.sql.SQLIntegrityConstraintViolationException: Column 'status' cannot be null ; Column 'status' cannot be null; nested exception is java.sql.SQLIntegrityConstraintViolationException: Column 'status' cannot be null
at org.springframework.jdbc.support.SQLExceptionSubclassTranslator.doTranslate(SQLExceptionSubclassTranslator.java:87) at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:70) at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:79) at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:88) at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:440) at com.sun.proxy.$Proxy170.update(Unknown Source) at org.mybatis.spring.SqlSessionTemplate.update(SqlSessionTemplate.java:287) at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.execute(MybatisMapperMethod.java:65) at com.baomidou.mybatisplus.core.override.MybatisMapperProxy$PlainMethodInvoker.invoke(MybatisMapperProxy.java:148) at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:89) at com.sun.proxy.$Proxy242.update(Unknown Source) at com.baomidou.mybatisplus.extension.service.IService.update(IService.java:167) at com.baomidou.mybatisplus.extension.service.IService.update(IService.java:157) at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:688) at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60) at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131) at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149) at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140) at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84) at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115) at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105) at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106) at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64) at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45) at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37) at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104) at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
印象中,lambdaUpdate().eq(Entity::id, 17834).set(Entity::status, null).set(...); 这种手动显示的set值的比更新策略优先级高的,详细的可以看下源码实现....
调用lambdaUpdate.set(Entity::status, null) 时,源码中set方法会维护一个sqlset的list集合,如下图
加载com.baomidou.mybatisplus.core.injector.methods.Update方法生成sql时会调用com.baomidou.mybatisplus.core.injector.AbstractMethod#sqlSet方法,调用时ew参数传的为true,当ew为true时执行以下代码 最终生成的update的set脚本大概如下:
<set>
<if test="et != null">
<if test="et['name'] != null">name=#{et.name},</if>
</if>
<if test="ew != null and ew.sqlSet != null">${ew.sqlSet}</if>
</set>
最终执行时,ew不为空 并且 ew.sqlSet也不为空,所以最终执行时会拼接上sql。 结论: 主动调用lambdaUpdate.set()方式比策略读取model的优先级高!!!
这只对entity生效
当前使用版本(必填,否则不予处理)
3.4.3
该问题是如何引起的?(确定最新版也有问题再提!!!)
系统配置 mybatis-plus: global-config: db-config: update-strategy: not_null lambdaUpdate().eq(Entity::id, 17834).set(Entity::status, null).set(...); 并没有过滤掉为空的set
重现步骤(如果有就写完整)
报错信息
Cause: java.sql.SQLIntegrityConstraintViolationException: Column 'status' cannot be null ; Column 'status' cannot be null; nested exception is java.sql.SQLIntegrityConstraintViolationException: Column 'status' cannot be null