多数据源配置下,解决 org.apache.ibatis.binding.BindingException Invalid bound statement (not found)问题

异常

本来 springboot 配置 mysql 配置正常,后来新加入了其他数据源,发现报错:

java 复制代码
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)

解决方案

多数据源配置下,解决 org.apache.ibatis.binding.BindingException Invalid bound statement (not found)问题

主要检查文件

1、检查mybatis.xml文件namespace名称是否和Mapper接口的全限定名是否一致

2、检查Mapper接口的方法在mybatis.xml中的每个语句的id是否一致

3、检查Mapper接口方法返回值是否匹配select元素配置的ResultMap,或者只配置ResultType

4、检查yml文件中的mapper的XML配置路径是否正确

5、Mybatis中接口与映射文件一定要同名或者必须在同一个包下,这个我没试过,好像是可以不同名的。

6、配置数据源的SqlSessionFactoryBean要使用MyBatisSqlSessionFactoryBean,这个也是鬼扯,MybatisPlus和Mybatis分清楚再说

7、编译没有把XML拷贝过来,可以用这招:

xml 复制代码
<build>      
    <resources>          
        <resource>               
            <directory>src/main/java</directory>               
            <includes>                   
                <include>**/*.xml</include>            
            </includes>
        </resource>
    </resources>
</build>

8、 启动会默认通过org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration * 类,我们是自定义的,所以需要排除MybatisAutoConfiguration

java 复制代码
@SpringBootApplication(exclude = MybatisAutoConfiguration.class)

9、Mapper接口文件,不同数据源需要放置在不同包下面。

可能的原因都在这里了,各位慢用!!!

附上SqlSessionFactoryBean代码

ds1.java:

java 复制代码
package com.****.****.Configurer;
 
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
 
import javax.sql.DataSource;
 
@Configuration
@MapperScan(basePackages = {"com.***.***.Mapper.ds1"}, sqlSessionFactoryRef = "ds1SqlSessionFactory")
public class MybatisDS1Config {
 
    @Bean(name = "ds1DataSource")
    @ConfigurationProperties(prefix = "spring.datasource.ds1")
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }
    /**
     * 配置事务管理器,不然事务不起作用
     *
     * @return
     */
    @Bean
    public PlatformTransactionManager transactionManagerDS1() {
        return new DataSourceTransactionManager(this.dataSource());
    }
    @Primary
    @Bean(name = "ds1SqlSessionFactory")
    public SqlSessionFactoryBean ds1sqlSessionFactory(@Qualifier("ds1DataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath*:mapping/ds1/*.xml"));
        sqlSessionFactoryBean.setTypeAliasesPackage("com.***.***.Entity");
        sqlSessionFactoryBean.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
        return sqlSessionFactoryBean;
 
        /**
         * 这里在applications.properties里面配置了
         * mybatis.type-aliases-package=com.jwt.springboot.dao
         * mybatis.mapper-locations=classpath:mapper/*Mapper.xml
         * 但多数据源情况下执行sql总会报:org.apache.ibatis.binding.BindingException:
         * Invalid bound statement (not found)........
         * 原因是 this.mapperLocations 为null
         *
         * 注!!!!这里有大坑, 因为这里是自定义的sqlSessionFactoryBean,所以导致
         * 没有启动时没有通过org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
         * 类的sqlSessionFactory(DataSource dataSource)方法自动装配sqlSessionFactoryBean
         * 自定义的sqlSessionFactoryBean所以也没设置mapperLocations
         * 故自定义实例化sqlSessionFactoryBean这里需要手动设置mapperLocations
         * 可参考:https://developer.aliyun.com/article/754124
         */
    }
}

ds2,java

java 复制代码
package com.***.***.Configurer;
 
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
 
import javax.sql.DataSource;
 
@Configuration
@MapperScan(basePackages = "com.***.***.Mapper.ds2", sqlSessionFactoryRef = "ds2SqlSessionFactory")
public class MybatisDS2Config {
 
    @Bean(name = "ds2DataSource")
    @ConfigurationProperties(prefix = "spring.datasource.ds2")
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }
    /**
     * 配置事务管理器,不然事务不起作用
     *
     * @return
     */
    @Bean
    public PlatformTransactionManager transactionManagerDS2() {
        return new DataSourceTransactionManager(this.dataSource());
    }
 
    @Bean("ds2SqlSessionFactory")
    public SqlSessionFactory ds2sqlSessionFactory(@Qualifier("ds2DataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath*:mapping/ds2/*.xml"));
        sqlSessionFactoryBean.setTypeAliasesPackage("com.***.***.Entity");
        sqlSessionFactoryBean.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
        return sqlSessionFactoryBean.getObject();
 
    }
}

yml配置:

yml 复制代码
spring:
  datasource:
    ds1: #主数据库,生产数据库
      username: ***
      password: ***
      #url中database为对应的数据库名称   //数据库名字
      jdbc-url: jdbc:mysql://***:3306/crmdb?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
      driver-class-name: com.mysql.cj.jdbc.Driver
 
    ds2: #从数据库,分析数据库
      username: ***
      password: ***
      #url中database为对应的数据库名称   //数据库名字
      jdbc-url: jdbc:mysql://***:3306/jmsns?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
      driver-class-name: com.mysql.cj.jdbc.Driver

文件目录结构:

另外,在Linux环境下:

java 复制代码
new PathMatchingResourcePatternResolver().getResources("classpath*:mapping/ds2/*.xml"));

可能出现找不到配置文件的问题,我用的替代方法是:

java 复制代码
new ClassPathResource[]{new ClassPathResource("/mapping/ds1/UserMapper.xml")}

总结

添加数据源的时候,只测试新的数据源确实可以,但是影响了旧的功能。

所以一定要注意影响范围。

参考资料

多数据源配置下,解决 org.apache.ibatis.binding.BindingException Invalid bound statement (not found)问题

本文由博客一文多发平台 OpenWrite 发布!

相关推荐
四谎真好看25 分钟前
Java 黑马程序员学习笔记(进阶篇18)
java·笔记·学习·学习笔记
桦说编程31 分钟前
深入解析CompletableFuture源码实现(2)———双源输入
java·后端·源码
java_t_t32 分钟前
ZIP工具类
java·zip
lang201509281 小时前
Spring Boot优雅关闭全解析
java·spring boot·后端
pengzhuofan2 小时前
第10章 Maven
java·maven
百锦再2 小时前
Vue Scoped样式混淆问题详解与解决方案
java·前端·javascript·数据库·vue.js·学习·.net
刘一说2 小时前
Spring Boot 启动慢?启动过程深度解析与优化策略
java·spring boot·后端
壹佰大多3 小时前
【spring如何扫描一个路径下被注解修饰的类】
java·后端·spring
百锦再3 小时前
对前后端分离与前后端不分离(通常指服务端渲染)的架构进行全方位的对比分析
java·开发语言·python·架构·eclipse·php·maven
DokiDoki之父3 小时前
Spring—注解开发
java·后端·spring