*当前使用版本*
Oracle OpenJDK version 17.0.5
mybatis-plus-boot-starter 3.5.2
springboot 2.7.4
问题描述
使用LambdaQueryWrapper查询报错,*Cannot invoke "Object.hashCode()" because "key" is null*
目前解决办法:
- 降低JDK版本为1.8
- 使用
QueryWrapper
测试代码:
Student anita3 = studentMapper.selectOne(new LambdaQueryWrapper<Student>()
.eq(Student::getNum, 2));
实体:
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("student")
@ApiModel(value="Student对象", description="")
public class Student extends Entity {
@TableId("id")
private String id;
@TableField("name")
private String name;
@TableField("num")
private Integer num;
}
mapper:
public interface StudentMapper extends Mapper<Student> {
}
报错信息:
2022-11-11 15:51:45.047 ERROR 11884 --- [nio-9607-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.builder.BuilderException: Error evaluating expression 'ew.sqlSegment != null and ew.sqlSegment != '' and ew.nonEmptyOfWhere'. Cause: org.apache.ibatis.ognl.OgnlException: sqlSegment [java.lang.NullPointerException: Cannot invoke "Object.hashCode()" because "key" is null]] with root cause
java.lang.NullPointerException: Cannot invoke "Object.hashCode()" because "key" is null
at java.base/java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:936) ~[na:na]
at com.baomidou.mybatisplus.core.toolkit.LambdaUtils.resolve(LambdaUtils.java:62) ~[mybatis-plus-core-3.3.2.jar:3.3.2]
at com.baomidou.mybatisplus.core.conditions.AbstractLambdaWrapper.columnToString(AbstractLambdaWrapper.java:63) ~[mybatis-plus-core-3.3.2.jar:3.3.2]
at com.baomidou.mybatisplus.core.conditions.AbstractLambdaWrapper.columnToString(AbstractLambdaWrapper.java:59) ~[mybatis-plus-core-3.3.2.jar:3.3.2]
at com.baomidou.mybatisplus.core.conditions.AbstractLambdaWrapper.columnToString(AbstractLambdaWrapper.java:39) ~[mybatis-plus-core-3.3.2.jar:3.3.2]
at com.baomidou.mybatisplus.core.conditions.AbstractWrapper.lambda$addCondition$ac69df92$1(AbstractWrapper.java:356) ~[mybatis-plus-core-3.3.2.jar:3.3.2]
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) ~[na:na]
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na]
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682) ~[na:na]
at com.baomidou.mybatisplus.core.conditions.segments.NormalSegmentList.childrenSqlSegment(NormalSegmentList.java:92) ~[mybatis-plus-core-3.3.2.jar:3.3.2]
at com.baomidou.mybatisplus.core.conditions.segments.AbstractISegmentList.getSqlSegment(AbstractISegmentList.java:103) ~[mybatis-plus-core-3.3.2.jar:3.3.2]
at com.baomidou.mybatisplus.core.conditions.segments.MergeSegments.getSqlSegment(MergeSegments.java:72) ~[mybatis-plus-core-3.3.2.jar:3.3.2]
at com.baomidou.mybatisplus.core.conditions.AbstractWrapper.getSqlSegment(AbstractWrapper.java:471) ~[mybatis-plus-core-3.3.2.jar:3.3.2]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
at org.apache.ibatis.ognl.OgnlRuntime.invokeMethodInsideSandbox(OgnlRuntime.java:1229) ~[mybatis-3.5.4.jar:3.5.4]
at org.apache.ibatis.ognl.OgnlRuntime.invokeMethod(OgnlRuntime.java:1214) ~[mybatis-3.5.4.jar:3.5.4]
at org.apache.ibatis.ognl.OgnlRuntime.getMethodValue(OgnlRuntime.java:2092) ~[mybatis-3.5.4.jar:3.5.4]
at org.apache.ibatis.ognl.ObjectPropertyAccessor.getPossibleProperty(ObjectPropertyAccessor.java:60) ~[mybatis-3.5.4.jar:3.5.4]
at org.apache.ibatis.ognl.ObjectPropertyAccessor.getProperty(ObjectPropertyAccessor.java:147) ~[mybatis-3.5.4.jar:3.5.4]
at org.apache.ibatis.ognl.OgnlRuntime.getProperty(OgnlRuntime.java:3233) ~[mybatis-3.5.4.jar:3.5.4]
at org.apache.ibatis.ognl.ASTProperty.getValueBody(ASTProperty.java:114) ~[mybatis-3.5.4.jar:3.5.4]
at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212) ~[mybatis-3.5.4.jar:3.5.4]
at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:258) ~[mybatis-3.5.4.jar:3.5.4]
at org.apache.ibatis.ognl.ASTChain.getValueBody(ASTChain.java:141) ~[mybatis-3.5.4.jar:3.5.4]
at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212) ~[mybatis-3.5.4.jar:3.5.4]
at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:258) ~[mybatis-3.5.4.jar:3.5.4]
at org.apache.ibatis.ognl.ASTNotEq.getValueBody(ASTNotEq.java:50) ~[mybatis-3.5.4.jar:3.5.4]
at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212) ~[mybatis-3.5.4.jar:3.5.4]
at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:258) ~[mybatis-3.5.4.jar:3.5.4]
at org.apache.ibatis.ognl.ASTAnd.getValueBody(ASTAnd.java:61) ~[mybatis-3.5.4.jar:3.5.4]
at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212) ~[mybatis-3.5.4.jar:3.5.4]
at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:258) ~[mybatis-3.5.4.jar:3.5.4]
at org.apache.ibatis.ognl.Ognl.getValue(Ognl.java:560) ~[mybatis-3.5.4.jar:3.5.4]
at org.apache.ibatis.ognl.Ognl.getValue(Ognl.java:524) ~[mybatis-3.5.4.jar:3.5.4]
at org.apache.ibatis.scripting.xmltags.OgnlCache.getValue(OgnlCache.java:46) ~[mybatis-3.5.4.jar:3.5.4]
at org.apache.ibatis.scripting.xmltags.ExpressionEvaluator.evaluateBoolean(ExpressionEvaluator.java:32) ~[mybatis-3.5.4.jar:3.5.4]
at org.apache.ibatis.scripting.xmltags.IfSqlNode.apply(IfSqlNode.java:34) ~[mybatis-3.5.4.jar:3.5.4]
at org.apache.ibatis.scripting.xmltags.MixedSqlNode.lambda$apply$0(MixedSqlNode.java:32) ~[mybatis-3.5.4.jar:3.5.4]
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) ~[na:na]
at org.apache.ibatis.scripting.xmltags.MixedSqlNode.apply(MixedSqlNode.java:32) ~[mybatis-3.5.4.jar:3.5.4]
at org.apache.ibatis.scripting.xmltags.TrimSqlNode.apply(TrimSqlNode.java:55) ~[mybatis-3.5.4.jar:3.5.4]
at org.apache.ibatis.scripting.xmltags.MixedSqlNode.lambda$apply$0(MixedSqlNode.java:32) ~[mybatis-3.5.4.jar:3.5.4]
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) ~[na:na]
at org.apache.ibatis.scripting.xmltags.MixedSqlNode.apply(MixedSqlNode.java:32) ~[mybatis-3.5.4.jar:3.5.4]
at org.apache.ibatis.scripting.xmltags.IfSqlNode.apply(IfSqlNode.java:35) ~[mybatis-3.5.4.jar:3.5.4]
at org.apache.ibatis.scripting.xmltags.MixedSqlNode.lambda$apply$0(MixedSqlNode.java:32) ~[mybatis-3.5.4.jar:3.5.4]
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) ~[na:na]
at org.apache.ibatis.scripting.xmltags.MixedSqlNode.apply(MixedSqlNode.java:32) ~[mybatis-3.5.4.jar:3.5.4]
at org.apache.ibatis.scripting.xmltags.DynamicSqlSource.getBoundSql(DynamicSqlSource.java:39) ~[mybatis-3.5.4.jar:3.5.4]
at org.apache.ibatis.mapping.MappedStatement.getBoundSql(MappedStatement.java:297) ~[mybatis-3.5.4.jar:3.5.4]
at com.baomidou.mybatisplus.core.executor.MybatisCachingExecutor.query(MybatisCachingExecutor.java:88) ~[mybatis-plus-core-3.3.2.jar:3.3.2]
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:147) ~[mybatis-3.5.4.jar:3.5.4]
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:140) ~[mybatis-3.5.4.jar:3.5.4]
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:76) ~[mybatis-3.5.4.jar:3.5.4]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:426) ~[mybatis-spring-2.0.4.jar:2.0.4]
at jdk.proxy2/jdk.proxy2.$Proxy75.selectOne(Unknown Source) ~[na:na]
at org.mybatis.spring.SqlSessionTemplate.selectOne(SqlSessionTemplate.java:159) ~[mybatis-spring-2.0.4.jar:2.0.4]
at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.execute(MybatisMapperMethod.java:108) ~[mybatis-plus-core-3.3.2.jar:3.3.2]
at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:96) ~[mybatis-plus-core-3.3.2.jar:3.3.2]
at jdk.proxy2/jdk.proxy2.$Proxy88.selectOne(Unknown Source) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.23.jar:5.3.23]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208) ~[spring-aop-5.3.23.jar:5.3.23]
at jdk.proxy2/jdk.proxy2.$Proxy89.selectOne(Unknown Source) ~[na:na]
at com.mpc.anitakit.life.Test.test(Test.java:32) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-5.3.23.jar:5.3.23]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) ~[spring-web-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) ~[spring-webmvc-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1071) ~[spring-webmvc-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:964) ~[spring-webmvc-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.23.jar:5.3.23]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:681) ~[tomcat-embed-core-9.0.65.jar:4.0.FR]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.23.jar:5.3.23]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) ~[tomcat-embed-core-9.0.65.jar:4.0.FR]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.65.jar:9.0.65]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.23.jar:5.3.23]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.23.jar:5.3.23]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.23.jar:5.3.23]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.23.jar:5.3.23]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.23.jar:5.3.23]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.23.jar:5.3.23]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:890) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1789) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
Comment From: shuaizai88
Entity 代码贴一下
Comment From: Sherry720
Entity
import java.io.Serializable;
public abstract class Entity implements Serializable {
}
StudentMapper
import com.mpc.common.mybatis.entity.Student;
import com.mpc.common.mybatis.base.Mapper;
public interface StudentMapper extends Mapper<Student> {
}
Mapper
package com.mpc.common.mybatis.base;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.mpc.common.model.BizException;
import com.mpc.common.mybatis.DbQuerier;
import com.mpc.common.mybatis.injector.CustomizedMapper;
import com.mpc.common.toolkit.AssertUtil;
import com.mpc.common.toolkit.ReflectUtil;
import org.springframework.transaction.annotation.Transactional;
import java.io.Serializable;
import java.util.*;
public interface Mapper<T extends Entity> extends CustomizedMapper<T> {
int DEFAULT_BATCH_SIZE = 20;
String TABLE_PK_NAME = "id";
default List<T> selectList() {
return selectList(Wrappers.emptyWrapper());
}
default List<T> selectByIds(Collection<? extends Serializable> idList) {
if (CollectionUtil.isEmpty(idList)) {
return CollectionUtil.newArrayList();
}
return selectBatchIds(idList);
}
/**
* 忽略null值的更新(值为null的字段忽略更新)
* @param entity
* @return
*/
default int updateIgnoredById(T entity) {
return updateById(entity);
}
/**
* 强制更新(值为null的字段也更新)
* @param entity
* @return
*/
default int updateForcedById(T entity) {
AssertUtil.isTrue(entity.getClass().isAnnotationPresent(TableName.class), "illegal entity.");
UpdateWrapper<T> wrapper = new UpdateWrapper<T>();
ReflectUtil.getFields(entity.getClass()).forEach(field -> {
try {
field.setAccessible(true);
if (field.isAnnotationPresent(TableId.class)) {
TableId tableId = field.getAnnotation(TableId.class);
wrapper.eq(tableId.value(), field.get(entity));
} else if (field.isAnnotationPresent(TableField.class)) {
TableField tableField = field.getAnnotation(TableField.class);
wrapper.set(tableField.value(), field.get(entity));
}
field.setAccessible(false);
} catch (Exception e) {
throw new BizException(e.getMessage(), e);
}
});
return update(entity, wrapper);
}
/**
* 批量更新
* @return
*/
@Transactional(rollbackFor = Exception.class)
default boolean updateBatchById(List<T> list) {
return updateBatchById(list, DEFAULT_BATCH_SIZE);
}
/**
* 批量更新
*/
@Transactional(rollbackFor = Exception.class)
default boolean updateBatchById(List<T> list, int batchSize) {
return batch(list, batchSize, batch -> customizedUpdateBatchById(batch));
}
/**
* 批量插入
* @return
*/
@Transactional(rollbackFor = Exception.class)
default boolean insertBatch(List<T> list) {
return insertBatch(list, DEFAULT_BATCH_SIZE);
}
/**
* 批量插入
*/
@Transactional(rollbackFor = Exception.class)
default boolean insertBatch(List<T> list, int batchSize) {
return batch(list, batchSize, batch -> customizedInsertBatch(batch));
}
default <R extends SFunction<T, ?>> int increment(Class<T> clazz, Serializable id, R r) {
return increment(clazz, id, r, 1);
}
/**
* 并发解决方案:直接采用数据库行锁特性,即sql语句自行+1的方式。
* --若先取值-计算-赋值,则存在并发问题,比如a取值时b已经取值计算,但是暂未赋值,造成a取值不准确等类似情景
*/
default <R extends SFunction<T, ?>> int increment(Class<T> clazz, Serializable id, R r, int step) {
if (step == 0) {
return 1;
}
String dbColumn = DbQuerier.getDbColumn(clazz, r);
UpdateWrapper<T> wrapper = new UpdateWrapper();
wrapper.setSql(dbColumn + " = " + dbColumn + (step > 0 ? " + " : " - ") + Math.abs(step));
wrapper.eq(TABLE_PK_NAME, id);
try {
return update(clazz.newInstance(), wrapper);
} catch (Exception e) {
throw new BizException(e.getMessage(), e);
}
}
default <UK extends SFunction<T, ?>> T selectByUk(UK uk, Serializable value) {
return selectOne(new LambdaQueryWrapper<T>().eq(uk, value));
}
default <UK extends SFunction<T, ?>> int updateByUk(T entity, UK uk, Serializable value) {
return update(entity, new LambdaQueryWrapper<T>().eq(uk, value));
}
default <Column extends SFunction<T, ?>> int deleteByColumn(Column column, Serializable value) {
return delete(new LambdaUpdateWrapper<T>().eq(column, value));
}
default <Column extends SFunction<T, ?>> List<T> selectList(Column column, Serializable value, Column... asc) {
return selectList(new LambdaQueryWrapper<T>().eq(column, value).orderByAsc(asc.length > 0, asc));
}
default <Column extends SFunction<T, ?>> int selectCount(Column column, Serializable value) {
return Optional.ofNullable(selectCount(new LambdaQueryWrapper<T>().eq(column, value))).orElse(0);
}
default <C extends SFunction<T, ?>> T selectOneByColumn(Hashtable<C, Serializable> columns) {
LambdaQueryWrapper<T> wrapper = new LambdaQueryWrapper<T>();
columns.entrySet().stream().forEach(i -> wrapper.eq(i.getKey(), i.getValue()));
return selectOne(wrapper);
}
default <C extends SFunction<T, ?>, V extends Serializable> T selectOneByColumn(C c1, V v1, C c2, V v2) {
Hashtable<C, Serializable> sf = new Hashtable<>();
sf.put(c1, v1);
sf.put(c2, v2);
return selectOneByColumn(sf);
}
default <C extends SFunction<T, ?>, V extends Serializable> T selectOneByColumn(C c1, V v1, C c2, V v2, C c3, V v3) {
Hashtable<C, Serializable> sf = new Hashtable<>();
sf.put(c1, v1);
sf.put(c2, v2);
sf.put(c3, v3);
return selectOneByColumn(sf);
}
}
CustomizedMapper
package com.mpc.common.mybatis.injector;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.google.common.collect.Lists;
import org.apache.ibatis.annotations.Param;
import org.springframework.cglib.core.internal.Function;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
public interface CustomizedMapper<T> extends BaseMapper<T> {
/**
* 自定义批量更新,条件为主键
* 如果要自动填充,@Param(xx) xx参数名必须是 list/collection/array 3个的其中之一
*/
boolean customizedUpdateBatchById(@Param("list") List<T> list);
/**
* 自定义批量插入
* 如果要自动填充,@Param(xx) xx参数名必须是 list/collection/array 3个的其中之一
*/
boolean customizedInsertBatch(@Param("list") List<T> list);
/**
* 批处理工具入口
* @param list
* @param batchSize
* @param func
* @return
*/
@Transactional(rollbackFor = Exception.class)
default boolean batch(List<T> list, int batchSize, Function<List<T>, Boolean> func) {
if (CollectionUtil.isEmpty(list)) {
return true;
}
if (batchSize < 1) {
return false;
}
if (list.size() <= batchSize) {
return func.apply(list);
}
Lists.partition(list, batchSize).forEach(batch -> func.apply(Lists.newArrayList(batch)));
return true;
}
}
Entity 代码贴一下
Comment From: shuaizai88
伙计,你到底用的3.3.2 还是3.5.2呢。我看你的jar好像是3.3.2,LambdaUtils.resolve 在3.5.2里面已经不存在了,你升级3.5.2测试下呢。
Comment From: Sherry720
伙计,你到底用的3.3.2 还是3.5.2呢。我看你的jar好像是3.3.2,LambdaUtils.resolve 在3.5.2里面已经不存在了,你升级3.5.2测试下呢。
还真是,mybatis-plus-boot-starter是3.5.2,但是mybatis-plus-generator是3.3.2,这两没对上,升级后测试已经可以了。感谢。
Comment From: MYZ6
伙计,你到底用的3.3.2 还是3.5.2呢。我看你的jar好像是3.3.2,LambdaUtils.resolve 在3.5.2里面已经不存在了,你升级3.5.2测试下呢。
厉害,佩服