異常 本來 springboot 配置 mysql 配置正常,後來新加入了其他數據源,發現報錯: org.apache.ibatis.binding.BindingException: Invalid bound statement (not found) 解決方案 多數據源配置下,解決 org.a ...
異常
本來 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 發佈!