架構說明:
先說下我們項目的大概架構,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點幾的版本支持,但是我們的版本依賴不能修改,所以這里沒有嘗試,有興趣的可以試試。