springboot配置多數(shù)據(jù)源(靜態(tài)和動(dòng)態(tài)數(shù)據(jù)源)
背景
在開發(fā)過程中,很多時(shí)候都會(huì)有垮數(shù)據(jù)庫操作數(shù)據(jù)的情況,需要同時(shí)配置多套數(shù)據(jù)源,即多個(gè)數(shù)據(jù)庫,保證不同的業(yè)務(wù)在不同的數(shù)據(jù)庫執(zhí)行操作,通過mapper來靈活的切換數(shù)據(jù)源。
本文以sqlserver和mysql混合數(shù)據(jù)源配置為例。
配置多數(shù)據(jù)源方案
1、通過mapper配置數(shù)據(jù)源
2、配置動(dòng)態(tài)數(shù)據(jù)源
具體實(shí)現(xiàn)
1)、 通過mapper配置數(shù)據(jù)源
(1)maven配置
? ? ? ? <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>com.microsoft.sqlserver</groupId> <artifactId>mssql-jdbc</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency>
(2)服務(wù)配置文件,application.yml
server: port: 9900 spring: datasource: db1: type: com.zaxxer.hikari.HikariDataSource driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver jdbc-url: jdbc:sqlserver://localhost:10009;DatabaseName=test username: sa password: 654321 db2: type: com.zaxxer.hikari.HikariDataSource driver-class-name: com.mysql.cj.jdbc.Driver jdbc-url: jdbc:mysql://localhost:3306/test2?useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true&allowMultiQueries=true username: root password: 123456
(3)添加數(shù)據(jù)庫配置
@Configuration public class DataSourceConfig { @Bean(name = "maindb") @Primary @ConfigurationProperties(prefix = "spring.datasource.db1") public DataSource businessDbDataSource() { return new HikariDataSource(); } @Bean(name = "seconddb") @ConfigurationProperties(prefix = "spring.datasource.db2") public DataSource newhomeDbDataSource() { return new HikariDataSource(); } }
(4)單獨(dú)配置每個(gè)數(shù)據(jù)源信息
注意:@Primary該注解理解為默認(rèn)數(shù)據(jù)源
包路徑配置可對(duì)比參考后面的項(xiàng)目結(jié)構(gòu)截圖
@Configuration @MapperScan(basePackages = {"com.gxin.datasource.dao.maindb"}, sqlSessionFactoryRef = "sqlSessionFactoryMaindb") public class DatasourceMainConfig { @Autowired @Qualifier("maindb") private DataSource dataSourceMaindb; @Bean @Primary public SqlSessionFactory sqlSessionFactoryMaindb() throws Exception { SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); factoryBean.setDataSource(dataSourceMaindb); factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/maindb/*.xml")); // 打印sql日志 // org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration(); // configuration.setLogImpl(StdOutImpl.class); // factoryBean.setConfiguration(configuration); return factoryBean.getObject(); } @Bean @Primary public SqlSessionTemplate sqlSessionTemplateMaindb() throws Exception { return new SqlSessionTemplate(sqlSessionFactoryMaindb()); } }
@Configuration @MapperScan(basePackages = {"com.gxin.datasource.dao.seconddb"}, sqlSessionFactoryRef = "sqlSessionFactorySeconddb") public class DatasourceSecondConfig { @Autowired @Qualifier("seconddb") private DataSource dataSourceSeconddb; @Bean public SqlSessionFactory sqlSessionFactorySeconddb() throws Exception { SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); factoryBean.setDataSource(dataSourceSeconddb); factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/seconddb/*.xml")); // 打印sql日志 // org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration(); // configuration.setLogImpl(StdOutImpl.class); // factoryBean.setConfiguration(configuration); return factoryBean.getObject(); } @Bean public SqlSessionTemplate sqlSessionTemplateSeconddb() throws Exception { return new SqlSessionTemplate(sqlSessionFactorySeconddb()); } }
(5)根據(jù)每個(gè)單獨(dú)的數(shù)據(jù)源的配置信息搭建mapper接口和mapper.xml文件
(6)配置mapper多數(shù)據(jù)源完成,下圖為完整的項(xiàng)目結(jié)構(gòu)
2)、 配置動(dòng)態(tài)數(shù)據(jù)源
(1)maven配置
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <dependency> <groupId>com.microsoft.sqlserver</groupId> <artifactId>mssql-jdbc</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency>
(2)服務(wù)配置文件,application.yml
server: port: 9901 spring: main: allow-bean-definition-overriding: true datasource: db1: type: com.zaxxer.hikari.HikariDataSource driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver jdbc-url: jdbc:sqlserver://localhost:10009;DatabaseName=test username: sa password: 654321 db2: type: com.zaxxer.hikari.HikariDataSource driver-class-name: com.mysql.cj.jdbc.Driver jdbc-url: jdbc:mysql://localhost:3306/test2?useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true&allowMultiQueries=true username: root password: 123456
(3)添加數(shù)據(jù)源列表
public interface DataSourceConstant { /** * 默認(rèn)數(shù)據(jù)庫 */ String MAIN = "MAIN"; /** * 第二數(shù)據(jù)庫 */ String SECOND = "SECOND"; }
(4)動(dòng)態(tài)數(shù)據(jù)源數(shù)據(jù)庫信息配置
@Configuration @EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class }) public class DynamicDataSourceConfig { // 核心數(shù)據(jù)庫 @Bean(name = DataSourceConstant.MAIN) @ConfigurationProperties(prefix = "spring.datasource.db1") public DataSource getMAINDataSource() { return new HikariDataSource(); } // 第二數(shù)據(jù)庫 @Bean(name = DataSourceConstant.SECOND) @ConfigurationProperties(prefix = "spring.datasource.db2") public DataSource getSECONDDataSource() { return new HikariDataSource(); } @Bean @Primary public DataSource dynamicDataSource() { Map<Object, Object> dataSourceMap = new HashMap<>(); dataSourceMap.put(DataSourceConstant.MAIN, getMAINDataSource()); dataSourceMap.put(DataSourceConstant.SECOND, getSECONDDataSource()); //設(shè)置動(dòng)態(tài)數(shù)據(jù)源 DynamicDataSource dynamicDataSource = new DynamicDataSource(); dynamicDataSource.setTargetDataSources(dataSourceMap); dynamicDataSource.setDefaultTargetDataSource(getMAINDataSource()); return dynamicDataSource; } }
(5)添加動(dòng)態(tài)數(shù)據(jù)源策略獲取配置,繼承AbstractRoutingDataSource
@Component public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { // 此處暫時(shí)返回固定 master 數(shù)據(jù)源, 后面按動(dòng)態(tài)策略修改 return DynamicDataSourceContextHolder.getContextKey(); } }
(6)數(shù)據(jù)源切換策略配置
public class DynamicDataSourceContextHolder { /** * 動(dòng)態(tài)數(shù)據(jù)源名稱上下文 */ private static final ThreadLocal<String> DATASOURCE_CONTEXT_KEY_HOLDER = new ThreadLocal<>(); /** * 設(shè)置/切換數(shù)據(jù)源 */ public static void setContextKey(String key) { DATASOURCE_CONTEXT_KEY_HOLDER.set(key); } /** * 獲取數(shù)據(jù)源名稱 */ public static String getContextKey() { String key = DATASOURCE_CONTEXT_KEY_HOLDER.get(); return key == null ? DataSourceConstant.MAIN : key; } /** * 刪除當(dāng)前數(shù)據(jù)源名稱 */ public static void removeContextKey() { DATASOURCE_CONTEXT_KEY_HOLDER.remove(); } }
(6.1) 這里寫掉了,補(bǔ)充數(shù)據(jù)庫會(huì)話配置
@Configuration public class SqlSessionConfig { @Autowired private DynamicDataSource source; public SqlSessionConfig() { } @Bean(name = {"sqlSessionFactoryBean"}) public SqlSessionFactoryBean getSessionFactory() throws Exception { SqlSessionFactoryBean factory = new SqlSessionFactoryBean(); factory.setDataSource(this.source); factory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml")); // 打印sql日志 org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration(); configuration.setLogImpl(StdOutImpl.class); factory.setConfiguration(configuration); return factory; } @Bean(name = {"sqlSession"}) public SqlSessionTemplate getSqlSession() throws Exception { return new SqlSessionTemplate(Objects.requireNonNull(getSessionFactory().getObject())); // SqlSessionFactory factory = this.getSessionFactory().getObject(); // return new SqlSessionTemplate(factory, ExecutorType.BATCH); } @Bean public DataSourceTransactionManager getDataSourceTransaction() { DataSourceTransactionManager manager = new DataSourceTransactionManager(); manager.setDataSource(this.source); return manager; } }
(7) 添加切換數(shù)據(jù)源標(biāo)識(shí)注解,默認(rèn)為MAIN數(shù)據(jù)源
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface DBS { /** * 數(shù)據(jù)源名稱 */ String value() default DataSourceConstant.MAIN; }
(8)通過配置的數(shù)據(jù)源標(biāo)識(shí)注解,動(dòng)態(tài)切換數(shù)據(jù)源
@Aspect @Component public class DynamicDataSourceAspect { @Pointcut("@annotation(com.gxin.dynamicdatasource.config.DBS)") public void dataSourcePointCut() { } @Around("dataSourcePointCut()") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { String dsKey = getDSAnnotation(joinPoint).value(); DynamicDataSourceContextHolder.setContextKey(dsKey); try { return joinPoint.proceed(); } finally { DynamicDataSourceContextHolder.removeContextKey(); } } /** * 根據(jù)類或方法獲取數(shù)據(jù)源注解 */ private DBS getDSAnnotation(ProceedingJoinPoint joinPoint) { Class<?> targetClass = joinPoint.getTarget().getClass(); DBS dsAnnotation = targetClass.getAnnotation(DBS.class); // 先判斷類的注解,再判斷方法注解 if (Objects.nonNull(dsAnnotation)) { return dsAnnotation; } else { MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); return methodSignature.getMethod().getAnnotation(DBS.class); } } }
(9)到此動(dòng)態(tài)數(shù)據(jù)源配置完成,一下的為使用情況,需要使用哪個(gè)數(shù)據(jù)源添加注解配置即可
@Repository public interface TestMapper { int getModelcount(); @DBS(DataSourceConstant.SECOND) int getUsercount(); }
(10)service層
@Service public class ServiceInfo { @Autowired private TestMapper mainMapper; public void datasource() { int modelcount = mainMapper.getModelcount(); System.out.println(modelcount); int usercount = mainMapper.getUsercount(); System.out.println(usercount); } }
(11)mapper. xml結(jié)構(gòu)目錄
(12)完整的項(xiàng)目結(jié)構(gòu)截圖
到此這篇關(guān)于springboot配置多數(shù)據(jù)源(靜態(tài)和動(dòng)態(tài)數(shù)據(jù)源)的文章就介紹到這了,更多相關(guān)springboot 多數(shù)據(jù)源內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot動(dòng)態(tài)數(shù)據(jù)源連接測(cè)試的操作詳解
- SpringBoot實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)源切換的方法總結(jié)
- SpringBoot中動(dòng)態(tài)數(shù)據(jù)源是實(shí)現(xiàn)與用途
- Springboot實(shí)現(xiàn)根據(jù)用戶ID切換動(dòng)態(tài)數(shù)據(jù)源
- 如何在Java SpringBoot項(xiàng)目中配置動(dòng)態(tài)數(shù)據(jù)源你知道嗎
- 詳解SpringBoot+Mybatis實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)源切換
- SpringBoot Mybatis動(dòng)態(tài)數(shù)據(jù)源切換方案實(shí)現(xiàn)過程
- 通過springboot+mybatis+druid配置動(dòng)態(tài)數(shù)據(jù)源
- SpringBoot整合MyBatisPlus配置動(dòng)態(tài)數(shù)據(jù)源的方法
- springboot 動(dòng)態(tài)數(shù)據(jù)源的實(shí)現(xiàn)方法(Mybatis+Druid)
- SpringBoot實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)源切換的項(xiàng)目實(shí)踐
相關(guān)文章
java web實(shí)現(xiàn)自動(dòng)登錄
這篇文章主要為大家詳細(xì)介紹了java web實(shí)現(xiàn)自動(dòng)登錄,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08MybatisPlus為何可以不用@MapperScan詳解
這篇文章主要給大家介紹了關(guān)于MybatisPlus為何可以不用@MapperScan的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用MybatisPlus具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2023-04-04Springboot中的Validation參數(shù)校驗(yàn)詳解
這篇文章主要介紹了Springboot中的Validation參數(shù)校驗(yàn)詳解,Springboot參數(shù)校驗(yàn)是一種常用的驗(yàn)證機(jī)制,在傳遞參數(shù)時(shí)進(jìn)行校驗(yàn),以確保參數(shù)的有效性和正確性,該機(jī)制可以幫助開發(fā)者在代碼實(shí)現(xiàn)前就避免一些常見的錯(cuò)誤,需要的朋友可以參考下2023-10-10Java文件(io)編程_基于File類的基本用法(必看篇)
下面小編就為大家?guī)硪黄狫ava文件(io)編程_基于File類的基本用法(必看篇)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-08-08java實(shí)現(xiàn)簡(jiǎn)單的推箱子小游戲
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡(jiǎn)單的推箱子小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-05-05JAVA TIMER簡(jiǎn)單用法學(xué)習(xí)
Timer類是用來執(zhí)行任務(wù)的類,它接受一個(gè)TimerTask做參數(shù)2013-07-07Mybatis-Plus動(dòng)態(tài)表名的實(shí)現(xiàn)示例
面對(duì)復(fù)雜多變的業(yè)務(wù)需求,動(dòng)態(tài)表名的處理變得愈發(fā)重要,本文主要介紹了Mybatis-Plus動(dòng)態(tài)表名的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下2024-07-07