楔子:當然,世上有很多優秀的女性,我也會被她們吸引。這對男人來說是理所當然的。但目光被吸引和內心被吸引是截然不同的。- 東野圭吾《黎明之街》
今日書簽
在一些應用場景中,可能需要連接多個不同的數據庫,例如連接不同的數據庫服務器或者連接主從數據庫。這段代碼就是為了實現這種多數據源的配置。
具體來說,這個類包含兩個內部靜態類:
- MyBatisDataSourceConfiguration4XMei: 這個類配置了第一個數據源,即 “xmei” 數據源。它使用了
@Primary 注解來指示這是默認的主數據源。這個數據源配置了一個 Druid 數據源,并配置了與該數據源相關的
SqlSessionFactory、事務管理器(DataSourceTransactionManager)和
SqlSessionTemplate。@MapperScan 注解用于指示需要掃描哪些包下的 Mapper 接口,并使用特定的
SqlSessionFactory。它還定義了 Mapper XML 文件的路徑,以及事務管理和 SqlSessionTemplate。 - MyBatisDataSourceConfiguration4XWei: 這個類配置了第二個數據源,即 “xwei” 數據源。它沒有使用
@Primary 注解,因此不是默認的主數據源。它使用了 @Qualifier 注解來指定特定的 Bean
名稱,用于解決多個數據源的沖突。與第一個數據源類似,它配置了一個 Druid 數據源,并定義了與該數據源相關的
SqlSessionFactory、事務管理器和 SqlSessionTemplate。
多數據源
使用 Service、Mapper、XML 所在包路徑區分默認數據源 與 第二數據源。
直接看代碼:
/*** 多數據源接入* dataSource4XMei 為 xmei 庫,為默認數據源,正常使用,此處以外無其它配置* dataSource4XWei 為 xwei 庫,為第二數據源,正常使用,此處以外無其它配置*/
@Configuration
public class MyBatisConfiguration {/*** 配置 SpringBoot 默認數據源,一般配置為主數據庫,此為 xmei*/@Configuration@MapperScan(basePackages = {"com.cw.tan.xmei.persistence.*"}, sqlSessionFactoryRef = "sqlSessionFactory4XMei")protected static class MyBatisDataSourceConfiguration4XMei {@Bean@Primary@ConfigurationProperties("spring.datasource.druid.xmei")public DataSource dataSource4XMei() {return DruidDataSourceBuilder.create().build();}@Bean@Primarypublic SqlSessionFactory sqlSessionFactory4XMei(DataSource dataSource4XMei) throws Exception {SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();sqlSessionFactoryBean.setDataSource(dataSource4XMei);sqlSessionFactoryBean.setMapperLocations(this.resolveMapperLocations());return sqlSessionFactoryBean.getObject();}private Resource[] resolveMapperLocations() {ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();List<String> mapperLocations = new ArrayList<>();mapperLocations.add("classpath*:com/cw/tan/xmei/persistence/**/*.xml");List<Resource> resources = new ArrayList();if (!CollectionUtils.isEmpty(mapperLocations)) {for (String mapperLocation : mapperLocations) {try {Resource[] mappers = resourceResolver.getResources(mapperLocation);resources.addAll(Arrays.asList(mappers));} catch (IOException e) {// ignore}}}return resources.toArray(new Resource[resources.size()]);}/*** 配置事務管理*/@Bean@Primarypublic DataSourceTransactionManager transactionManager4XMei(DataSource dataSource4XMei) {return new DataSourceTransactionManager(dataSource4XMei);}@Bean@Primarypublic SqlSessionTemplate sqlSessionTemplate4XMei(SqlSessionFactory sqlSessionFactory4XMei) {return new SqlSessionTemplate(sqlSessionFactory4XMei);}}/*** 配置第二數據源,注意 mapper 掃描路徑和上面的區分開*/@Configuration@MapperScan(basePackages = {"com.cw.tan.xwei.log.mapper","com.cw.tan.xwei.sms.mapper", "com.cw.tan.xwei.job.mapper"}, sqlSessionFactoryRef = "sqlSessionFactory4XWei")protected static class MyBatisDataSourceConfiguration4XWei {@Bean(name = "dataSource4XWei")@ConfigurationProperties("spring.datasource.druid.xwei")public DataSource dataSource4XWei() {return DruidDataSourceBuilder.create().build();}@Bean(name = "sqlSessionFactory4XWei")public SqlSessionFactory sqlSessionFactory4XWei(@Qualifier("dataSource4XWei") DataSource dataSource4XWei) throws Exception {SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();sqlSessionFactoryBean.setDataSource(dataSource4XWei);sqlSessionFactoryBean.setMapperLocations(this.resolveMapperLocations());return sqlSessionFactoryBean.getObject();}private Resource[] resolveMapperLocations() {ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();List<String> mapperLocations = new ArrayList<>();mapperLocations.add("classpath*:com/cw/tan/xwei/log/**/*.xml");mapperLocations.add("classpath*:com/cw/tan/xwei/sms/**/*.xml");mapperLocations.add("classpath*:com/cw/tan/xwei/job/**/*.xml");List<Resource> resources = new ArrayList<>();if (!CollectionUtils.isEmpty(mapperLocations)) {mapperLocations.forEach(mapperLocation -> {try {Resource[] mappers = resourcePatternResolver.getResources(mapperLocation);resources.addAll(Arrays.asList(mappers));} catch (IOException e) {// ignore}});}return resources.toArray(new Resource[resources.size()]);}@Bean(name = "transactionManager4XWei")public DataSourceTransactionManager transactionManager4XWei(@Qualifier("dataSource4XWei") DataSource dataSource4XWei) {return new DataSourceTransactionManager(dataSource4XWei);}@Bean(name = "sqlSessionTemplate4XWei")public SqlSessionTemplate sqlSessionTemplate4XWei(@Qualifier("sqlSessionFactory4XWei") SqlSessionFactory sqlSessionFactory4XWei) {return new SqlSessionTemplate(sqlSessionFactory4XWei);}}
}
注意:上述配置,請確認自己的默認數據源、第二數據源對應Service、DAO文件所在的包路徑,如果路徑指向不對,可能會出現以下異常:
2023-08-17 16:09:33.981 [TID:] [main] WARN AnnotationConfigServletWebServerApplicationContext.refresh():559 - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘dataDataSyncController’: Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type ‘com.cw.tan.xwei.job.IDataSyncService’ available: expected single matching bean but found 2: dataSyncServiceImpl,IDataSyncService
總結
這段代碼通過兩個內部靜態類分別配置了兩個不同的數據源(xmei 和 xwei)。每個數據源配置了對應的 Druid 數據源、SqlSessionFactory、事務管理器和 SqlSessionTemplate。這種多數據源配置適用于需要訪問多個不同數據庫的場景,如在一個系統中同時連接多個數據庫來進行不同的操作,比如主數據庫和日志數據庫、數據庫與業務庫數據同步等。
如果還需要擴展更多數據源,則可將上述 第二數據源配置 進行復制粘貼,然后做相應名稱、包路徑的修改即可。