当前使用版本(必填,否则不予处理)
3.4.3版本,没有问题
该问题是如何引起的?(确定最新版也有问题再提!!!)
更新版本到3.4.3.2及以上
仅仅升级了版本出现了问题,确认是mybatis-plus内部代码问题
重现步骤(如果有就写完整)
mybatis-plus-boot-starter 从3.4.3升级到3.4.3.2版本或以上版本
我的代码:
- 调用代码
downloadService.saveOrUpdateBatch(updateItemList, Item.class, Item::getExamId, Item::getItemCode);
updateItemList --数据列表(Item)
- downloadService的实现
`
@Transactional(rollbackFor = Exception.class)
public
@Transactional(rollbackFor = Exception.class)
public <T> boolean saveOrUpdateBatch(Collection<? extends BaseEntity<T>> entityList, int batchSize, Class<T> entityClass, SFunction<T,?>...columns) {
TableInfo tableInfo = TableInfoHelper.getTableInfo(entityClass);
Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!");
String keyProperty = tableInfo.getKeyProperty();
Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!");
return executeBatch(entityList, batchSize, (sqlSession, entity) -> {
Object idVal = ReflectionKit.getFieldValue(entity, tableInfo.getKeyProperty());
boolean insert = true;
if (columns != null && columns.length > 0 && StringUtils.checkValNull(idVal)) {
T t = selectOne(tableInfo,sqlSession,(T)entity,columns);--------------------报错方法
if (t != null) {
idVal = ReflectionKit.getFieldValue(entity, keyProperty);
insert = false;
}
}
if (insert) {
//不添加已删删除数据
if (entity.getIsDelete() == null || entity.getIsDelete() == GeneralEnums.DeleteEnums.NO.getKey()) {
entity.setUpdateInfo(entity.getUpdateUser(), true);
sqlSession.insert(tableInfo.getSqlStatement(SqlMethod.INSERT_ONE.getMethod()), entity);
} else {
entity.setId(null);
}
} else {
entity.setUpdateInfo(entity.getUpdateUser(),false);
MapperMethod.ParamMap<Object> param = new MapperMethod.ParamMap<>();
UpdateWrapper updateWrapper = new UpdateWrapper<>();
updateWrapper.eq(tableInfo.getKeyColumn(),idVal);
//更新删除标识,防止唯一约束冲突
if (entity.getIsDelete() != null && entity.getIsDelete() != GeneralEnums.DeleteEnums.NO.getKey()){
updateWrapper.set("is_delete",IdWorker.getId());
}
param.put(Constants.ENTITY, entity);
param.put(Constants.WRAPPER,updateWrapper);
sqlSession.update(tableInfo.getSqlStatement(SqlMethod.UPDATE.getMethod()), param);
}
},entityClass);
}
protected <E> boolean executeBatch(Collection<? extends BaseEntity<E>> list, int batchSize, BiConsumer<SqlSession, BaseEntity<E>> consumer, Class<E> entityClass) {
Assert.isFalse(batchSize < 1, "batchSize must not be less than one");
return !CollectionUtils.isEmpty(list) && executeBatch(sqlSession -> {
int size = list.size();
int i = 1;
for (BaseEntity<E> element : list) {
consumer.accept(sqlSession, element);
if ((i % batchSize == 0) || i == size) {
sqlSession.flushStatements();
}
i++;
}
},entityClass);
}
protected boolean executeBatch(Consumer<SqlSession> consumer, Class entityClass) {
SqlSessionFactory sqlSessionFactory = SqlHelper.sqlSessionFactory(entityClass);
SqlSessionHolder sqlSessionHolder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sqlSessionFactory);
boolean transaction = TransactionSynchronizationManager.isSynchronizationActive();
if (sqlSessionHolder != null) {
SqlSession sqlSession = sqlSessionHolder.getSqlSession();
//原生无法支持执行器切换,当存在批量操作时,会嵌套两个session的,优先commit上一个session
//按道理来说,这里的值应该一直为false。
sqlSession.commit(!transaction);
}
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
if (!transaction) {
log.warn("SqlSession [" + sqlSession + "] was not registered for synchronization because DataSource is not transactional");
}
try {
consumer.accept(sqlSession);
//非事物情况下,强制commit。
sqlSession.commit(!transaction);
return true;
} catch (Throwable t) {
sqlSession.rollback();
Throwable unwrapped = ExceptionUtil.unwrapThrowable(t);
if (unwrapped instanceof RuntimeException) {
MyBatisExceptionTranslator myBatisExceptionTranslator
= new MyBatisExceptionTranslator(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(), true);
throw Objects.requireNonNull(myBatisExceptionTranslator.translateExceptionIfPossible((RuntimeException) unwrapped));
}
throw ExceptionUtils.mpe(unwrapped);
} finally {
sqlSession.close();
}
}
/**
* 根据id查询
* @param tableInfo
* @param sqlSession
* @param <T>
* @return
*/
public <T>T selectById(TableInfo tableInfo,SqlSession sqlSession){
return sqlSession.selectOne(tableInfo.getSqlStatement(SqlMethod.SELECT_BY_ID.getMethod()));
}
---保错方法
public
**实际报错代码**
return sqlSession.selectOne(tableInfo.getSqlStatement(SqlMethod.SELECT_ONE.getMethod()),parame);
}
`
- 说明
实际报错方法 sqlSession.selectOne(tableInfo.getSqlStatement(SqlMethod.SELECT_ONE.getMethod()),parame);
仅仅升级了版本出现了问题,确认是mybatis-plus内部代码问题
报错信息
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException:
Error querying database. Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for com.fplcloud.exam.modules.system.mapper.ItemMapper.selectOne
Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for com.fplcloud.exam.modules.system.mapper.ItemMapper.selectOne
at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:96)
at com.fplcloud.exam.modules.examsystem.service.DownloadService.executeBatch(DownloadService.java:998)
at com.fplcloud.exam.modules.examsystem.service.DownloadService.executeBatch(DownloadService.java:961)
at com.fplcloud.exam.modules.examsystem.service.DownloadService.saveOrUpdateBatch(DownloadService.java:926)
at com.fplcloud.exam.modules.examsystem.service.DownloadService.saveOrUpdateBatch(DownloadService.java:918)
at com.fplcloud.exam.modules.examsystem.service.DownloadService$$FastClassBySpringCGLIB$$1cff083c.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708)
at com.fplcloud.exam.modules.examsystem.service.DownloadService$$EnhancerBySpringCGLIB$$10b7ab14.saveOrUpdateBatch(<generated>)
at com.fplcloud.exam.modules.examsystem.service.Impl.ExamSystemItemServiceImpl.saveExamItem(ExamSystemItemServiceImpl.java:167)
at com.fplcloud.exam.modules.examsystem.service.Impl.ExamSystemItemServiceImpl$$FastClassBySpringCGLIB$$39e8cad7.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708)
at com.fplcloud.exam.modules.examsystem.service.Impl.ExamSystemItemServiceImpl$$EnhancerBySpringCGLIB$$79862c1e.saveExamItem(<generated>)
at com.fplcloud.exam.modules.system.service.impl.AsyncServiceImpl.downloadServerData(AsyncServiceImpl.java:126)
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.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.interceptor.AsyncExecutionInterceptor.lambda$invoke$0(AsyncExecutionInterceptor.java:115)
at java.base/java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:264)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:829)
Comment From: nieqiurong
3.4.3.2已经删除了selectOne方法的注入了,你可以将方法注入一下.
Comment From: przygrubyu5
好的,我已经添加了
`public class DownSqlInjector extends DefaultSqlInjector {
@Override
public List
}`
Comment From: nieqiurong
好的,我已经添加了
`public class DownSqlInjector extends DefaultSqlInjector { @OverRide public List getMethodList(Class<?> mapperClass, TableInfo tableInfo) { List methodList = super.getMethodList(mapperClass, tableInfo); methodList.add(new SelectOne()); return methodList; }
}`
也能自己改动一下调用selectList把,那样和后面的也匹配点.