乐趣区

关于后端:多数据源-ibatisbindingBindingException-Invalid-bound-statement

异样

原本 springboot 配置 mysql 配置失常,起初新退出了其余数据源,发现报错:

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 拷贝过去,能够用这招:

<build>      
    <resources>          
        <resource>               
            <directory>src/main/java</directory>               
            <includes>                   
                <include>**/*.xml</include>            
            </includes>
        </resource>
    </resources>
</build>

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

@SpringBootApplication(exclude = MybatisAutoConfiguration.class)

9、Mapper 接口文件,不同数据源须要搁置在不同包上面。

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

附上 SqlSessionFactoryBean 代码

ds1.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

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 配置:

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 环境下:

new PathMatchingResourcePatternResolver().getResources("classpath*:mapping/ds2/*.xml"));

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

new ClassPathResource[]{new ClassPathResource("/mapping/ds1/UserMapper.xml")}

总结

增加数据源的时候,只测试新的数据源的确能够,然而影响了旧的性能。

所以肯定要留神影响范畴。

参考资料

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

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

退出移动版