当前使用版本(必填,否则不予处理)

3.3.0,测试3.4.0也有此问题

该问题是如何引起的?(确定最新版也有问题再提!!!)

MySQL数据库晚于springboot程序启动时,数据库成功连上,普通查询可以使用,xml自定义的mapper方法报Invalid bound statement (not found)。 而程序在数据库启动后启动不会有此问题,可以正常使用。

xml内该调用方法用databaseId指定多个数据库类型,分别对应MySQL和oracle语法。 经测试,若将两个方法合并,去掉databaseId字段,数据库晚于程序启动也不会出现此问题。

重现步骤(如果有就写完整)

xml自定义sql,使用databaseId指定多个数据库类型; 先启动springboot服务,等报出数据库连接失败后启动数据库。

报错信息

Caused by: org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.company.project.uda.mapper.DeviceMapper.getDevices at org.apache.ibatis.binding.MapperMethod$SqlCommand.(MapperMethod.java:235) at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.(MybatisMapperMethod.java:50) at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.lambda$cachedMapperMethod$0(MybatisMapperProxy.java:101) at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660) at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.cachedMapperMethod(MybatisMapperProxy.java:100) at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:95) at com.sun.proxy.$Proxy105.getDevices(Unknown Source) at com.company.project.service.dev.DeviceServiceImpl.selectByCond(DeviceServiceImpl.java:326) at com.company.project.service.dev.DeviceServiceImpl$$FastClassBySpringCGLIB$$4e3d11aa.invoke() at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:367) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691) at com.company.project.service.dev.DeviceServiceImpl$$EnhancerBySpringCGLIB$$b447397c.selectByCond() at com.company.project.controller.dev.DeviceApiController.selectByCond(DeviceApiController.java:117) 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.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792) at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ... 33 more

Comment From: passer002

问题定位为mybatis中VendorDatabaseIdProvider在获取数据库类型时需要进行连接,若未连接,则无法获取到。

private String getDatabaseProductName(DataSource dataSource) throws SQLException { Connection con = null; try { // 需要进行数据库连接,未成功抛出异常 con = dataSource.getConnection(); DatabaseMetaData metaData = con.getMetaData(); return metaData.getDatabaseProductName(); } finally { if (con != null) { try { con.close(); } catch (SQLException e) { // ignored } } } }

目前是通过重写org.apache.ibatis.mapping.VendorDatabaseIdProvider.getDatabaseId(DataSource)方法解决。