Dubbo远程rpc调用Mybatis-Plus自带的方法引发的几个错误
架构说明:
先说下我们项目的大概架构,nacos用作配置和服务注册发现中心。其他微服务在nacos注册,通过Dubbo进行远程调用。
提前说明,为了方便,我这里讲调用者=消费者,提供者=生产者。
我这里的消费者,没有其他过多的包类,可以简单理解,只有一个包,包里每个类,对应一个数据库表的维护,操作都是调用生产者提供的服务接口。
出现的错误一:
这段代码是在消费这里面写的,需要远程调用scpIcpbussService的list接口
LambdaQueryWrapper<Icpbuss> wrapper = new LambdaQueryWrapper<>(); wrapper.select(Icpbuss::getId).eq(Icpbuss::getSOrgCode, item.getSOrgCode()) .eq(Icpbuss::getSupplierSystem, item.getSupplierSystem()) .eq(Icpbuss::getROrgCode, item.getROrgCode()) .eq(Icpbuss::getRequirementSystem, item.getRequirementSystem()); List<Icpbuss> dataList = IcpbussService.list(wrapper);
运行后,就会报错,如下
com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: can not find lambda cache for this entity [com.xxx.xxx.basic.entity.xxxIcpbuss]
com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: can not find lambda cache for this entity [com.xxx.xxx.basic.entity.xxxIcpbuss] at com.baomidou.mybatisplus.core.toolkit.ExceptionUtils.mpe(ExceptionUtils.java:49) at com.baomidou.mybatisplus.core.toolkit.Assert.isTrue(Assert.java:38) at com.baomidou.mybatisplus.core.toolkit.Assert.notNull(Assert.java:72) at com.baomidou.mybatisplus.core.conditions.AbstractLambdaWrapper.tryInitCache(AbstractLambdaWrapper.java:89) at com.baomidou.mybatisplus.core.conditions.AbstractLambdaWrapper.getColumnCache(AbstractLambdaWrapper.java:78) at com.baomidou.mybatisplus.core.conditions.AbstractLambdaWrapper.columnToString(AbstractLambdaWrapper.java:62) at com.baomidou.mybatisplus.core.conditions.AbstractLambdaWrapper.lambda$columnsToString$0(AbstractLambdaWrapper.java:53) at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948) at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482) at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472) at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708) at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499) at com.baomidou.mybatisplus.core.conditions.AbstractLambdaWrapper.columnsToString(AbstractLambdaWrapper.java:53) at com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper.select(LambdaQueryWrapper.java:84) at com.xxx.xxx.xxx.spi.IcpbussConsumerStrategySpi.lambda$saveData$2(IcpbussConsumerStrategySpi.java:100) at java.util.ArrayList.forEach(ArrayList.java:1259) at com.xxx.xxx.xxx.spi.IcpbussConsumerStrategySpi.saveData(IcpbussConsumerStrategySpi.java:98) at com.xxx.xxx.xxx.spi.IcpbussConsumerStrategySpi.receive(IcpbussConsumerStrategySpi.java:82) at com.xxx.xxx.xxx.spi.IcpbussConsumerStrategySpi.receive(IcpbussConsumerStrategySpi.java:55) at com.xxx.xxx.xxx.spi.IcpbussConsumerStrategySpi$$FastClassBySpringCGLIB$$f3488070.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:783) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753) at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:89) at com.xxx.xxx.xxx.aspect.xxxAspect.doAroundAdvice(xxxAspect.java:54) at com.xxx.xxx.xxx.aspect.xxxAspect$$FastClassBySpringCGLIB$$8e07f5f5.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689) at com.xxx.xxx.xxx.aspect.xxxAspect$$EnhancerBySpringCGLIB$$ddfaddf9.doAroundAdvice(<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.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:634) at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:624) at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:72) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753) 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:753) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:698) at com.xxx.xxx.xxx.spi.IcpbussConsumerStrategySpi$$EnhancerBySpringCGLIB$$7d4ce1e5.receive(<generated>) at com.xxx.xxx.spi.dispatcher.support.DefaultDataOutSpi.receiveProcessor(DefaultDataOutSpi.java:98) at com.xxx.xxx.spi.dispatcher.support.DefaultDataOutSpi.lambda$null$1(DefaultDataOutSpi.java:63) at org.apache.camel.support.processor.DelegateSyncProcessor.process(DelegateSyncProcessor.java:65) at org.apache.camel.processor.errorhandler.RedeliveryErrorHandler$RedeliveryTask.doRun(RedeliveryErrorHandler.java:810) at org.apache.camel.processor.errorhandler.RedeliveryErrorHandler$RedeliveryTask.run(RedeliveryErrorHandler.java:718) at org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.schedule(DefaultReactiveExecutor.java:187) at org.apache.camel.impl.engine.DefaultReactiveExecutor.scheduleMain(DefaultReactiveExecutor.java:64) at org.apache.camel.processor.Pipeline.process(Pipeline.java:184) at org.apache.camel.impl.engine.CamelInternalProcessor.process(CamelInternalProcessor.java:398) at org.apache.camel.impl.engine.DefaultAsyncProcessorAwaitManager.process(DefaultAsyncProcessorAwaitManager.java:83) at org.apache.camel.support.AsyncProcessorSupport.process(AsyncProcessorSupport.java:41) at org.apache.camel.component.rabbitmq.RabbitConsumer.doHandleDelivery(RabbitConsumer.java:109) at org.apache.camel.component.rabbitmq.RabbitConsumer.handleDelivery(RabbitConsumer.java:84) at com.rabbitmq.client.impl.ConsumerDispatcher$5.run(ConsumerDispatcher.java:149) at com.rabbitmq.client.impl.ConsumerWorkService$WorkPoolRunnable.run(ConsumerWorkService.java:104) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748)
原因以及解决方法:百度以及自己尝试,发现Dubbo远程调用不支持LambdaQueryWrapper或者QueryWrapper等类型的传递。尽量改用传递实体等,需要构建查询条件的,还是在提供者的实现类里面去使用LambdaQueryWrapper或者QueryWrapper等;还有说法是Mybatis-Plus的版本太低,但是我这里没有尝试。
如果上面的错误你改了,可以正常运行了,那就不用看下面的错误二了。
错误二:
当我改了错误一以后,又出现了这个错误,如下:
百度到的,都是说没有配置主数据,之类的,但是我去了服务的提供者看配置,是配置的,可以正常使用。这里说明下,我服务的消费着是不需要数据库连接的,全程都是通过Dubbo调用远程服务。
出现错误代码是:service.saveBatch(dataList); 说明:saveBatch是Mybatis-Plus中Service自带的方法。
org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is com.baomidou.dynamic.datasource.exception.CannotFindDataSourceException: dynamic-datasource can not find primary datasource at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:309) at org.springframework.transaction.support.AbstractPlatformTransactionManager.startTransaction(AbstractPlatformTransactionManager.java:400) at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373) at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:595) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:382) 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:753) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:698) at org.apache.dubbo.common.bytecode.proxy2$$EnhancerBySpringCGLIB$$e170fea3.saveBatch(<generated>) at com.xxx.xxx.xxx.spi.IcpbussConsumerStrategySpi.saveData(IcpbussConsumerStrategySpi.java:98) at com.xxx.xxx.xxx.spi.IcpbussConsumerStrategySpi.receive(IcpbussConsumerStrategySpi.java:82) at com.xxx.xxx.xxx.spi.IcpbussConsumerStrategySpi.receive(IcpbussConsumerStrategySpi.java:55) at com.xxx.xxx.xxx.spi.IcpbussConsumerStrategySpi$$FastClassBySpringCGLIB$$f3488070.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:783) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753) at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:89) at com.xxx.xxx.xxx.aspect.xxxAspect.doAroundAdvice(xxxAspect.java:54) at com.xxx.xxx.xxx.aspect.xxxAspect$$FastClassBySpringCGLIB$$8e07f5f5.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689) at com.xxx.xxx.xxx.aspect.xxxAspect$$EnhancerBySpringCGLIB$$f7832c33.doAroundAdvice(<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.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:634) at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:624) at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:72) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753) 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:753) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:698) at com.xxx.xxx.xxx.spi.IcpbussConsumerStrategySpi$$EnhancerBySpringCGLIB$$dc9a1d21.receive(<generated>) at com.xxx.xxx.spi.dispatcher.support.DefaultDataOutSpi.receiveProcessor(DefaultDataOutSpi.java:98) at com.xxx.xxx.spi.dispatcher.support.DefaultDataOutSpi.lambda$null$1(DefaultDataOutSpi.java:63) at org.apache.camel.support.processor.DelegateSyncProcessor.process(DelegateSyncProcessor.java:65) at org.apache.camel.processor.errorhandler.RedeliveryErrorHandler$RedeliveryTask.doRun(RedeliveryErrorHandler.java:810) at org.apache.camel.processor.errorhandler.RedeliveryErrorHandler$RedeliveryTask.run(RedeliveryErrorHandler.java:718) at org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.schedule(DefaultReactiveExecutor.java:187) at org.apache.camel.impl.engine.DefaultReactiveExecutor.scheduleMain(DefaultReactiveExecutor.java:64) at org.apache.camel.processor.Pipeline.process(Pipeline.java:184) at org.apache.camel.impl.engine.CamelInternalProcessor.process(CamelInternalProcessor.java:398) at org.apache.camel.impl.engine.DefaultAsyncProcessorAwaitManager.process(DefaultAsyncProcessorAwaitManager.java:83) at org.apache.camel.support.AsyncProcessorSupport.process(AsyncProcessorSupport.java:41) at org.apache.camel.component.rabbitmq.RabbitConsumer.doHandleDelivery(RabbitConsumer.java:109) at org.apache.camel.component.rabbitmq.RabbitConsumer.handleDelivery(RabbitConsumer.java:84) at com.rabbitmq.client.impl.ConsumerDispatcher$5.run(ConsumerDispatcher.java:149) at com.rabbitmq.client.impl.ConsumerWorkService$WorkPoolRunnable.run(ConsumerWorkService.java:104) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) Caused by: com.baomidou.dynamic.datasource.exception.CannotFindDataSourceException: dynamic-datasource can not find primary datasource at com.baomidou.dynamic.datasource.DynamicRoutingDataSource.determinePrimaryDataSource(DynamicRoutingDataSource.java:90) at com.baomidou.dynamic.datasource.DynamicRoutingDataSource.getDataSource(DynamicRoutingDataSource.java:141) at com.baomidou.dynamic.datasource.DynamicRoutingDataSource.determineDataSource(DynamicRoutingDataSource.java:77) at com.baomidou.dynamic.datasource.ds.AbstractRoutingDataSource.getConnection(AbstractRoutingDataSource.java:43) at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:265) ... 55 more
原因以及解决方法:初步判断的原因是如果消费者,调用的是提供者服务的Mybatis-Plus自带的底层方法,比如list,save等方法时候,就会出现上面的错误。解决办法是在你的接口层重新封装一下。
Mybatis-Plus自带的方法部分。
封装如下:
// 接口层 public interface IXxxService extends IService<ScpIcpbuss> { /** * 保存数据 * */ public void saveNew(XXX xxx); } // 实现层 @Service @DubboService(version = "1.0.0") public class XxxServiceImpl extends ServiceImpl<xxxMapper, xxx> implements IXxxService { @Override public void saveNew(XXX xxx) { this.save(xxx); } }
代码调用说明:
@Slf4j @Service public class IcpbussConsumerStrategySpi{ @DubboReference(version = "1.0.0") private IXxxService service; // 保存数据 private void saveData(XXX xxx) { // 这样调用会报错,调用的是Mybatis-plus的方法 service.save(xxx); // 这样正确,不会出现多数据源未配置主数据源的错误,调用的是我们自己封装的saveNew方法 service.saveNew(xxx); } }
最后:
目前只是一种简单的解决方法,因为项目比较急,没有深入研究,仅供参考,提供一种思路,如有错漏或者有大佬知道原因的可以留言指教。
百度到的说Mybatis-Plus不支持Dubbo远程调用使用LambdaQueryWrapper之类的传参,但是也有说3点几的版本支持,但是我们的版本依赖不能修改,所以这里没有尝试,有兴趣的可以试试。