Spring Boot多数据源配置详解
前几天,公司提了个需求,对一个项目进行二次开发,在开发过程中,需要配置多数据源来进行数据库的操作。下面我将主键探索总结的配置流程和遇到的各种坑做以总结,希望能够帮到遇到同样问题的友友。有错的地方,请各位大佬留言指出。
1.双数据源配置
首先是数据源配置:application.yml文件,这里要注意的是单数据源下的数据库路径为url,多数据源下为jdbc-url
spring:
#单数据源
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://127.0.0.1:3306/meeting?serverTimezone=UTC
username: root
password: 1111
# 多数据源
datasource:
one: #数据源1的配置
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://127.0.0.1:3306/meeting?serverTimezone=UTC
username: root
password: 1111
two: #数据源2的配置
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://127.0.0.1:3306/xin-master?serverTimezone=UTC
username: root
password: 1111
注意点:当我们使用多数据源配置的时候,mybatis和plus的配置就不需要在.yml文件中配置了,下面就是关于数据源的一些其他config配置了。
2.当数据源配置好之后,就需要注意我们的项目结构了,由于是两套数据源,所以对应的mapper和xml文件应当放在不同的包或者目录下
将每个数据源对应的mapper接口,和*Mapper.xml文件分开放在不同的包下,保证在进行数据库的装配时,根据我们的不同包,对应好不同的数据源。
3.对不同的数据源进行不同的配置
数据源在配置时候要有主从之分,这里我的one数据源为主库,他的配置如下,代码过程请仔细看,主库和从库配置略有不同
> “主库配置如下”
@Configuration
> 这里进行mapper接口路径的扫描
@MapperScan(basePackages = "com.sbp.api.mapper.mapper1", sqlSessionTemplateRef = "db1SqlSessionTemplate")
public class DataSourceOneConfig {
> 这里是一个不同点,主库要加"@Primary"注解
@Bean
@ConfigurationProperties(prefix = "spring.datasource.one")
@Primary
public DataSource db1DataSource() {
return DataSourceBuilder.create().build();
}
> 这里是一个不同点,主库要加"@Primary"注解
@Bean
@Primary
@Lazy //这个是懒加载的注解,根据自己项目需要看是否添加
public SqlSessionFactory db1SqlSessionFactory(@Qualifier("db1DataSource") DataSource dataSource) throws Exception {
MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
bean.setDataSource(dataSource);
//开启驼峰
MybatisConfiguration configuration = new MybatisConfiguration();
configuration.setMapUnderscoreToCamelCase(true);
bean.setConfiguration(configuration);
> "这个方法的调用是指定当前数据源的mybatis的Xml文件的路径"
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapping/mapper1/*.xml"));
return bean.getObject();
}
@Bean
@Primary
public DataSourceTransactionManager db1TransactionManager(@Qualifier("db1DataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean
@Primary
@Lazy
public SqlSessionTemplate db1SqlSessionTemplate(@Qualifier("db1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
从库配置如下
和主库配置基本相同,只不过主库的每个Bean前要加”@Primary”注解,从库不加。
@Configuration
@MapperScan(basePackages = "com.sbp.api.mapper.mapper2", sqlSessionTemplateRef = "sqlSessionTemplate2")
public class DataSourceTwoConfig {
@Bean(name = "dataSource2")
@ConfigurationProperties(prefix = "spring.datasource.two")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "sqlSessionFactory2")
public SqlSessionFactory db1SqlSessionFactory(@Qualifier("db1DataSource") DataSource dataSource) throws Exception {
MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
bean.setDataSource(dataSource);
//开启驼峰
MybatisConfiguration configuration = new MybatisConfiguration();
configuration.setMapUnderscoreToCamelCase(true);
bean.setConfiguration(configuration);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapping/mapper2/*.xml"));
return bean.getObject();
}
@Bean(name = "transactionManager2")
public DataSourceTransactionManager transactionManager(@Qualifier("dataSource2") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "sqlSessionTemplate2")
public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory2") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
将上面的内容配置好之后,基本就完成了双数据源的配置,但是为了项目的健康运行,还需要检查下面的一些配置:
1.项目主启动类是否添加了@MapperScan(“*”)注解,如果添加了,请将他去掉,因为我们的每个数据源在config配置类中都单独指定了basePackages 扫描路径。这里再添加上可能会报错。因为我再测试过程中遇到了。
2.项目启动后主库访问可能没有问题,但是从库访问报:Invalid bound statement (not found):com…selectAll这种错误
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.hnchances.api.mapper.mapper2.ymssm.YmSsmMapper.insterPhone
网上解决办法我找着都试了一遍,好多大佬都有遇到这种问题,提供的问题解决思路如下
通常导致这种原因的大致有以下这几种情况
1、mapper的namespace 有问题
2、 xxMapper的方法在xxMapper.xml中没有,调用那个方法就报错
3、没有正确配置ResultMap,或者只配置ResultType!等等。
当筛选完毕上边这些配置都没有问题,那么就要考虑是不是mybatis或者mybatis-plus自动加载了mapper,导致我们再配置类中手动配置的xml路径失效,导致的 Invalid bound statement (not found)问题。
需要将二者的自动加载排除:在主启动类中进行排除即可:
> "这里@SpringBootApplication中的语句就是排除二者的自动mapper加载,如果你的项目中只有其中一个依赖的话,就只需要排除一个就行,"
> "我的项目在之前开发时,他们两个mybatis持久层框架都使用了,所以两个都需要排除"
@SpringBootApplication(exclude = {MybatisAutoConfiguration.class, MybatisPlusAutoConfiguration.class})
// 开启定时任务
@EnableScheduling
//@MapperScan("com.hnchances.api.mapper") //多数据源,这里不需要包扫描
@Import({DataSourceOneConfig.class, DataSourceTwoConfig.class})
public class ApiApplication {
public static void main(String[] args) {
SpringApplication.run(ApiApplication.class, args);
}
}
至此,spring boot多数据源配置和遇坑报错问题基本都解决了,如果友友们还遇到其他问题,并且找到了解决思路的话,欢迎留下文章链接供大家参考。