在SpringBoot項目中動態(tài)切換數(shù)據(jù)源和數(shù)據(jù)庫的詳細步驟
前言
在許多企業(yè)級應(yīng)用中,可能需要根據(jù)不同的業(yè)務(wù)需求來切換不同的數(shù)據(jù)庫,如讀寫分離、分庫分表等場景。Spring Boot 提供了靈活的數(shù)據(jù)源配置方式,可以通過動態(tài)切換數(shù)據(jù)源來實現(xiàn)這些需求。
本文將介紹如何在 Spring Boot 項目中實現(xiàn)動態(tài)切換數(shù)據(jù)源和數(shù)據(jù)庫的方案。我們將使用 Spring 的 AbstractRoutingDataSource
來實現(xiàn)動態(tài)切換數(shù)據(jù)源。
步驟一:引入依賴
首先,確保 Spring Boot 項目引入了以下依賴,主要包括 Spring Data JPA 和 MySQL 驅(qū)動(如果使用 MySQL 數(shù)據(jù)庫)。在 pom.xml
文件中添加這些依賴:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.zaxxer</groupId> <artifactId>HikariCP</artifactId> <!-- 使用 HikariCP 作為連接池 --> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency>
步驟二:配置多個數(shù)據(jù)源
在 application.properties
或 application.yml
中配置多個數(shù)據(jù)源,假設(shè)我們配置了主數(shù)據(jù)源和從數(shù)據(jù)源。
application.properties 示例:
# 主數(shù)據(jù)源配置 spring.datasource.primary.url=jdbc:mysql://localhost:3306/primary_db spring.datasource.primary.username=root spring.datasource.primary.password=root_password spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.primary.hikari.maximum-pool-size=10 # 從數(shù)據(jù)源配置 spring.datasource.secondary.url=jdbc:mysql://localhost:3306/secondary_db spring.datasource.secondary.username=root spring.datasource.secondary.password=root_password spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.secondary.hikari.maximum-pool-size=10
步驟三:自定義動態(tài)數(shù)據(jù)源
Spring Boot 默認的配置是固定的單一數(shù)據(jù)源,但我們可以通過自定義 AbstractRoutingDataSource
來實現(xiàn)動態(tài)數(shù)據(jù)源切換。
1. 自定義 DynamicDataSource 類
AbstractRoutingDataSource
是 Spring 提供的一個用于路由到不同數(shù)據(jù)源的抽象類,我們繼承該類并重寫 determineCurrentLookupKey()
方法,根據(jù)當(dāng)前線程或請求上下文來決定使用哪個數(shù)據(jù)源。
public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDataSourceType(); } }
2. 定義 DataSourceContextHolder 類
為了實現(xiàn)線程安全地存儲當(dāng)前數(shù)據(jù)源的上下文,我們使用 ThreadLocal
來保存當(dāng)前線程的數(shù)據(jù)源標(biāo)識。
public class DataSourceContextHolder { private static final ThreadLocal<String> contextHolder = new ThreadLocal<>(); public static void setDataSourceType(String dataSourceType) { contextHolder.set(dataSourceType); } public static String getDataSourceType() { return contextHolder.get(); } public static void clearDataSourceType() { contextHolder.remove(); } }
3. 配置動態(tài)數(shù)據(jù)源
在配置類中,將多個數(shù)據(jù)源(如主數(shù)據(jù)庫和從數(shù)據(jù)庫)與 DynamicDataSource
關(guān)聯(lián),并將 DynamicDataSource
設(shè)置為 Spring 管理的數(shù)據(jù)源。
@Configuration @EnableTransactionManagement @EnableJpaRepositories(basePackages = "com.example.repository") public class DataSourceConfig { @Primary @Bean public DynamicDataSource dynamicDataSource( @Qualifier("primaryDataSource") DataSource primaryDataSource, @Qualifier("secondaryDataSource") DataSource secondaryDataSource) { Map<Object, Object> targetDataSources = new HashMap<>(); targetDataSources.put("primary", primaryDataSource); targetDataSources.put("secondary", secondaryDataSource); DynamicDataSource dynamicDataSource = new DynamicDataSource(); dynamicDataSource.setDefaultTargetDataSource(primaryDataSource); dynamicDataSource.setTargetDataSources(targetDataSources); return dynamicDataSource; } @Primary @Bean @ConfigurationProperties(prefix = "spring.datasource.primary") public DataSource primaryDataSource() { return DataSourceBuilder.create().build(); } @Bean @ConfigurationProperties(prefix = "spring.datasource.secondary") public DataSource secondaryDataSource() { return DataSourceBuilder.create().build(); } }
步驟四:切換數(shù)據(jù)源
為了動態(tài)切換數(shù)據(jù)源,我們可以在需要切換數(shù)據(jù)源的地方設(shè)置數(shù)據(jù)源類型(如讀寫分離、業(yè)務(wù)模塊分庫等)。
1. 在服務(wù)層切換數(shù)據(jù)源
在服務(wù)方法中,我們可以通過 DataSourceContextHolder.setDataSourceType("primary")
或 DataSourceContextHolder.setDataSourceType("secondary")
來切換數(shù)據(jù)源。
@Service public class DataService { // 使用主數(shù)據(jù)源 public void usePrimaryDataSource() { DataSourceContextHolder.setDataSourceType("primary"); // 執(zhí)行主數(shù)據(jù)庫相關(guān)操作 } // 使用從數(shù)據(jù)源 public void useSecondaryDataSource() { DataSourceContextHolder.setDataSourceType("secondary"); // 執(zhí)行從數(shù)據(jù)庫相關(guān)操作 } // 清除數(shù)據(jù)源設(shè)置 public void clearDataSource() { DataSourceContextHolder.clearDataSourceType(); } }
2. 在控制器層切換數(shù)據(jù)源
在控制器層中,可以根據(jù)請求的不同選擇使用不同的數(shù)據(jù)源。
@RestController @RequestMapping("/data") public class DataController { @Autowired private DataService dataService; @GetMapping("/usePrimary") public String usePrimaryDataSource() { dataService.usePrimaryDataSource(); return "Using Primary DataSource"; } @GetMapping("/useSecondary") public String useSecondaryDataSource() { dataService.useSecondaryDataSource(); return "Using Secondary DataSource"; } }
步驟五:使用AOP統(tǒng)一切換數(shù)據(jù)源
為了更優(yōu)雅地切換數(shù)據(jù)源并解耦,我們可以通過 AOP(面向切面編程)來統(tǒng)一處理數(shù)據(jù)源切換。我們可以創(chuàng)建一個自定義注解來標(biāo)識哪些方法需要切換數(shù)據(jù)源。
1. 自定義注解
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface DataSourceSwitch { String value() default "primary"; // 默認使用主數(shù)據(jù)源 }
2. 切面類實現(xiàn)
創(chuàng)建切面類,在方法執(zhí)行前根據(jù)注解指定的數(shù)據(jù)源值來切換數(shù)據(jù)源。
@Aspect @Component public class DataSourceAspect { @Before("@annotation(dataSourceSwitch)") public void switchDataSource(DataSourceSwitch dataSourceSwitch) { String dataSourceType = dataSourceSwitch.value(); DataSourceContextHolder.setDataSourceType(dataSourceType); } @After("@annotation(dataSourceSwitch)") public void clearDataSource(DataSourceSwitch dataSourceSwitch) { DataSourceContextHolder.clearDataSourceType(); } }
3. 使用注解切換數(shù)據(jù)源
@Service public class DataService { @DataSourceSwitch("primary") public void usePrimaryDataSource() { // 使用主數(shù)據(jù)源 } @DataSourceSwitch("secondary") public void useSecondaryDataSource() { // 使用從數(shù)據(jù)源 } }
總結(jié)
通過在 Spring Boot 中實現(xiàn)動態(tài)數(shù)據(jù)源切換,我們可以靈活地管理不同數(shù)據(jù)庫的使用,滿足不同業(yè)務(wù)場景的需求。無論是簡單的讀寫分離、分庫還是更復(fù)雜的業(yè)務(wù)需求,都可以通過動態(tài)切換數(shù)據(jù)源來完成。通過結(jié)合 AOP 和注解,我們可以更加優(yōu)雅地管理和切換數(shù)據(jù)源,避免了硬編碼和重復(fù)代碼的情況,提升了代碼的可維護性和擴展性。
以上就是在SpringBoot項目中動態(tài)切換數(shù)據(jù)源和數(shù)據(jù)庫的詳細步驟的詳細內(nèi)容,更多關(guān)于SpringBoot動態(tài)切換數(shù)據(jù)源和數(shù)據(jù)庫的資料請關(guān)注腳本之家其它相關(guān)文章!
- SpringBoot實現(xiàn)數(shù)據(jù)源動態(tài)切換的最佳姿勢
- SpringBoot項目中如何動態(tài)切換數(shù)據(jù)源、數(shù)據(jù)庫
- SpringBoot實現(xiàn)動態(tài)數(shù)據(jù)源切換的項目實踐
- SpringBoot實現(xiàn)動態(tài)數(shù)據(jù)源切換的方法總結(jié)
- 使用SpringBoot動態(tài)切換數(shù)據(jù)源的實現(xiàn)方式
- Springboot實現(xiàn)多數(shù)據(jù)源切換詳情
- SpringBoot多數(shù)據(jù)源切換實現(xiàn)代碼(Mybaitis)
- SpringBoot實現(xiàn)動態(tài)切換數(shù)據(jù)源的示例代碼
相關(guān)文章
使用Spirng Boot Admin監(jiān)控Spring Cloud應(yīng)用項目
這篇文章主要介紹了使用Spirng Boot Admin監(jiān)控Spring Cloud應(yīng)用項目,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-05-05Java static方法用法實戰(zhàn)案例總結(jié)
這篇文章主要介紹了Java static方法用法,結(jié)合具體案例形式總結(jié)分析了java static方法功能、使用方法及相關(guān)操作注意事項,需要的朋友可以參考下2019-09-09SpringBoot請求參數(shù)傳遞與接收說明小結(jié)
這篇文章主要介紹了SpringBoot請求參數(shù)傳遞與接收,本文通過示例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-12-12Spring Data JPA 關(guān)鍵字Exists的用法說明
這篇文章主要介紹了Spring Data JPA 關(guān)鍵字Exists的用法說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06一篇文章徹底弄懂SpringBoot項目jdk版本及依賴不兼容問題
這篇文章主要給大家介紹了關(guān)于徹底弄懂SpringBoot項目jdk版本及依賴不兼容問題的相關(guān)資料,文中通過圖文介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2023-01-01restTemplate發(fā)送get與post請求并且?guī)?shù)問題
這篇文章主要介紹了restTemplate發(fā)送get與post請求并且?guī)?shù)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07Mybatis-plus獲取雪花算法生成的ID并返回生成ID
本文主要介紹了Mybatis-plus獲取雪花算法生成的ID并返回生成ID,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-09-09Zuul1與Spring Cloud Gateway的區(qū)別及說明
Zuul1基于Servlet阻塞IO,穩(wěn)定但高并發(fā)易耗盡線程;SpringCloudGateway采用非阻塞IO和Netty,性能更優(yōu)、內(nèi)置限流,適合高并發(fā)場景,兩者均支持SpringCloud集成,但Zuul1有更多生產(chǎn)落地案例2025-07-07Spring Boot整合MyBatis連接Oracle數(shù)據(jù)庫的步驟全紀(jì)錄
這篇文章主要給大家介紹了關(guān)于Spring Boot整合MyBatis連接Oracle數(shù)據(jù)庫的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-07-07