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多数据源配置和遇坑报错问题基本都解决了,如果友友们还遇到其他问题,并且找到了解决思路的话,欢迎留下文章链接供大家参考。