Springboot多數據源配置和切換

一、Springboot配置雙數據源

在Spring Boot應用程序中配置多個數據源是很常見的需求。由於Spring Boot的自動配置機制,使得我們可以輕鬆優雅的實現多數據源配置和切換。 若要配置雙數據源,則需要使用Spring Boot的自動裝配機制執行以下操作:

1. 確保我們的應用程序中依賴了Spring Boot的MyBatis Starter,這將為MyBatis集成提供必要的依賴關係和自動配置。在pom.xml文件中添加以下依賴:

<dependency>
  <groupId>org.mybatis.spring.boot</groupId>
  <artifactId>mybatis-spring-boot-starter</artifactId>
  <version>2.1.0</version>
</dependency>

2. 在application.properties中配置雙數據源的各項信息:

# primary datasource
spring.datasource.primary.url=jdbc:mysql://localhost:3306/primary_db
spring.datasource.primary.username=dbuser
spring.datasource.primary.password=dbpassword
spring.datasource.primary.driver-class-name=com.mysql.jdbc.Driver

# secondary datasource
spring.datasource.secondary.url=jdbc:mysql://localhost:3306/secondary_db
spring.datasource.secondary.username=dbuser
spring.datasource.secondary.password=dbpassword
spring.datasource.secondary.driver-class-name=com.mysql.jdbc.Driver

3. 創建主數據源和次數據源的數據源類:

@Configuration
@MapperScan(basePackages = "com.example.demo.mapper.primary", sqlSessionTemplateRef = "primarySqlSessionTemplate")
public class PrimaryDataSourceConfig {

    @Autowired
    private DataSourceProperties dataSourceProperties;

    @Bean(name = "primaryDataSource")
    @Primary
    public DataSource primaryDataSource() {
        return dataSourceProperties.initializeDataSourceBuilder().build();
    }

    @Bean(name = "primarySqlSessionFactory")
    @Primary
    public SqlSessionFactory primarySqlSessionFactory(@Qualifier("primaryDataSource") DataSource primaryDataSource) throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(primaryDataSource);
        return sessionFactory.getObject();
    }

    @Bean(name = "primaryTransactionManager")
    @Primary
    public DataSourceTransactionManager primaryTransactionManager(@Qualifier("primaryDataSource") DataSource primaryDataSource) {
        return new DataSourceTransactionManager(primaryDataSource);
    }

    @Bean(name = "primarySqlSessionTemplate")
    @Primary
    public SqlSessionTemplate primarySqlSessionTemplate(@Qualifier("primarySqlSessionFactory") SqlSessionFactory primarySqlSessionFactory) {
        return new SqlSessionTemplate(primarySqlSessionFactory);
    }
}

@Configuration
@MapperScan(basePackages = "com.example.demo.mapper.secondary", sqlSessionTemplateRef  = "secondarySqlSessionTemplate")
public class SecondaryDataSourceConfig {

    @Autowired
    private DataSourceProperties dataSourceProperties;

    @Bean(name = "secondaryDataSource")
    public DataSource secondaryDataSource() {
        return dataSourceProperties.initializeDataSourceBuilder().build();
    }

    @Bean(name = "secondarySqlSessionFactory")
    public SqlSessionFactory secondarySqlSessionFactory(@Qualifier("secondaryDataSource") DataSource secondaryDataSource) throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(secondaryDataSource);
        return sessionFactory.getObject();
    }

    @Bean(name = "secondaryTransactionManager")
    public DataSourceTransactionManager secondaryTransactionManager(@Qualifier("secondaryDataSource") DataSource secondaryDataSource) {
        return new DataSourceTransactionManager(secondaryDataSource);
    }

    @Bean(name = "secondarySqlSessionTemplate")
    public SqlSessionTemplate secondarySqlSessionTemplate(@Qualifier("secondarySqlSessionFactory") SqlSessionFactory secondarySqlSessionFactory) {
        return new SqlSessionTemplate(secondarySqlSessionFactory);
    }
}

4. 創建controller並在其中注入主數據源的mapper和次數據源的mapper

@RestController
@RequestMapping("/users")
public class UserController {

    @Autowired
    private PrimaryUserMapper primaryUserMapper;

    @Autowired
    private SecondaryUserMapper secondaryUserMapper;

    @GetMapping("/primary/list")
    public List getPrimaryUsers() {
        return primaryUserMapper.getAll();
    }

    @GetMapping("/secondary/list")
    public List getSecondaryUsers() {
        return secondaryUserMapper.getAll();
    }
}

5. 啟動應用並測試多數據源的配置是否正確。

二、Mybatis多數據源配置SpringBoot

當使用Mybatis作為數據持久層框架時,需要按以下步驟在SpringBoot中配置多數據源:

1. 在pom.xml文件中添加以下依賴關係:

<dependency>
  <groupId>org.mybatis.spring.boot</groupId>
  <artifactId>mybatis-spring-boot-starter</artifactId>
  <version>2.1.0</version>
</dependency>

2. 在application.properties或application.yml文件中配置數據源信息:

# primary datasource
spring.datasource.primary.url=jdbc:mysql://localhost:3306/primary_db
spring.datasource.primary.username=dbuser
spring.datasource.primary.password=dbpassword
spring.datasource.primary.driver-class-name=com.mysql.jdbc.Driver

# secondary datasource
spring.datasource.secondary.url=jdbc:mysql://localhost:3306/secondary_db
spring.datasource.secondary.username=dbuser
spring.datasource.secondary.password=dbpassword
spring.datasource.secondary.driver-class-name=com.mysql.jdbc.Driver

3. 創建數據源類、SqlSessionFactory、SqlSessionTemplate和TransactionManager:

@Configuration
@MapperScan(basePackages = "com.example.demo.mapper.primary", sqlSessionTemplateRef = "primarySqlSessionTemplate")
public class PrimaryDataSourceConfig {

    @Autowired
    private DataSource primaryDataSource;

    @Bean(name = "primarySqlSessionFactory")
    @Primary
    public SqlSessionFactory primarySqlSessionFactory() throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(primaryDataSource);
        return sessionFactory.getObject();
    }

    @Bean(name = "primaryTransactionManager")
    @Primary
    public DataSourceTransactionManager primaryTransactionManager() {
        return new DataSourceTransactionManager(primaryDataSource);
    }

    @Bean(name = "primarySqlSessionTemplate")
    @Primary
    public SqlSessionTemplate primarySqlSessionTemplate(@Qualifier("primarySqlSessionFactory") SqlSessionFactory primarySqlSessionFactory) {
        return new SqlSessionTemplate(primarySqlSessionFactory);
    }
}

@Configuration
@MapperScan(basePackages = "com.example.demo.mapper.secondary", sqlSessionTemplateRef  = "secondarySqlSessionTemplate")
public class SecondaryDataSourceConfig {

    @Autowired
    private DataSource secondaryDataSource;

    @Bean(name = "secondarySqlSessionFactory")
    public SqlSessionFactory secondarySqlSessionFactory() throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(secondaryDataSource);
        return sessionFactory.getObject();
    }

    @Bean(name = "secondaryTransactionManager")
    public DataSourceTransactionManager secondaryTransactionManager() {
        return new DataSourceTransactionManager(secondaryDataSource);
    }

    @Bean(name = "secondarySqlSessionTemplate")
    public SqlSessionTemplate secondarySqlSessionTemplate(@Qualifier("secondarySqlSessionFactory") SqlSessionFactory secondarySqlSessionFactory) {
        return new SqlSessionTemplate(secondarySqlSessionFactory);
    }
}

4. 創建主數據源mapper和次數據源mapper,並在其中分別使用@Qualifier註解注入對應的數據源的SqlSessionTemplate。

5. 對於需要使用次數據源的Service或Dao類中,使用@Qualifier註解指定對應的SqlSessionTemplate。

6. 啟動應用並測試多數據源的配置是否正確。

三、Springboot動態配置數據源

無論是配置雙數據源還是多數據源,都需要在application.properties或application.yml文件中預先配置好數據源信息。然而,在生產環境中,可能需要根據用戶的訪問請求,動態選擇不同的數據源。因此,需要在運行時動態配置數據源,具體步驟如下:

1. 在pom.xml文件中添加以下依賴關係:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

2. 配置與數據源相關的bean:

@Configuration
public class DynamicDataSourceConfig {

    @Autowired
    private DataSourceProperties dataSourceProperties;

    private final Map dataSources = new ConcurrentHashMap();

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(dataSourceProperties.getDriverClassName());
        dataSource.setUrl(dataSourceProperties.getUrl());
        dataSource.setUsername(dataSourceProperties.getUsername());
        dataSource.setPassword(dataSourceProperties.getPassword());
        return new DynamicRoutingDataSource(dataSource);
    }

    @Bean
    public DataSourceTransactionManager dataSourceTransactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());
        return sessionFactory.getObject();
    }

    @Bean
    public SqlSessionTemplate sqlSessionTemplate() throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory());
    }
}

3. 創建動態數據源類DynamicRoutingDataSource和動態數據源上下文ThreadLocal:

public class DynamicRoutingDataSource extends AbstractRoutingDataSource {

    public DynamicRoutingDataSource(DataSource defaultTargetDataSource) {
        super.setDefaultTargetDataSource(defaultTargetDataSource);
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return DynamicDataSourceContextHolder.getDataSourceKey();
    }
}

public class DynamicDataSourceContextHolder {

    private static final ThreadLocal CONTEXT_HOLDER = new ThreadLocal();

    public static void setDataSourceKey(String key) {
        CONTEXT_HOLDER.set(key);
    }

    public static String getDataSourceKey() {
        return CONTEXT_HOLDER.get();
    }

    public static void clearDataSourceKey() {
        CONTEXT_HOLDER.remove();
    }
}

4. 創建DynamicDataSourceAspect類,在函數執行前獲取數據源的key並設置到DynamicDataSourceContextHolder中,函數執行完畢後清除DynamicDataSourceContextHolder。

@Aspect
@Component
public class DynamicDataSourceAspect {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Before("execution(* com.example.demo.service.*.*(..))")
    public void before(JoinPoint point) {
        String dataSourceKey = point.getSignature().getName().contains("primary") ? "primary" : "secondary";
        DynamicDataSourceContextHolder.setDataSourceKey(dataSourceKey);
        logger.info(String.format("設置數據源為 %s", dataSourceKey));
    }

    @After("execution(* com.example.demo.service.*.*(..))")
    public void after(JoinPoint point) {
        DynamicDataSourceContextHolder.clearDataSourceKey();
        logger.info("清除數據源");
    }
}

5. 在需要多數據源的Service實現類中,添加以下注解,這將激活DynamicDataSourceAspect,從而動態設置數據源:

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private PrimaryUserMapper primaryUserMapper;

    @Autowired
    private SecondaryUserMapper secondaryUserMapper;

    @Primary
    @DataSource(key = "primary")
    public List getAllPrimaryUsers() {
        return primaryUserMapper.getAll();
    }

    @DataSource(key = "secondary")
    public List getAllSecondaryUsers() {
        return secondaryUserMapper.getAll();
    }

    // ...
}

四、Springboot配置多數據源Druid

如果需要使用連接池,可以選擇使用阿里巴巴的Druid。具體步驟如下:

1. 在pom.xml文件中添加以下依賴關係:

<dependency>
    <groupId>com.alibaba
    <artifactId>druid-spring-boot-starter
    <version>1.2.5
</dependency>

2. 在application.properties或application.yml文件中配置DruidDataSource的各項信息:

# primary datasource
spring.datasource.primary.url=jdbc:mysql://localhost:3306/primary_db?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true
spring.datasource.primary.username=dbuser
spring.datasource.primary.password=dbpassword
spring.datasource.primary.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.primary.type=com.alibaba.druid.pool.DruidDataSource
# druid specific config
spring.datasource.primary.initial-size=0
spring.datasource.primary.min-idle=0
spring.datasource.primary.max-active=20
spring.datasource.primary.max-wait=-1
spring.datasource.primary.time-between-eviction-runs-millis=60000
spring.datasource.primary.min-evictable-idle-time-millis=300000
spring.datasource.primary.validation-query=SELECT 1 FROM DUAL
spring.datasource.primary.test-while-idle=true
spring.datasource.primary.test-on-borrow=false
spring.datasource.primary.test-on-return=false
spring.datasource.primary.pool-prepared-statements=true
spring.datasource.primary.max-pool-prepared-statement-per-connection-size=20
spring.datasource.primary.filters=stat,wall,log4j
spring.datasource.primary.connection-properties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000

# secondary datasource
spring.datasource.secondary.url=jdbc:mysql://localhost:3306/secondary_db?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true
spring.datasource.secondary.username=dbuser
spring.datasource.secondary.password=dbpassword
spring.datasource.secondary.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.secondary.type=com.alibaba.druid.pool.DruidDataSource
# druid specific config
spring.datasource.secondary.initial-size=0
spring.datasource.secondary.min-idle=0
spring.datasource.secondary.max-active=20
spring.datasource.secondary.max-wait=-1
spring.datasource.secondary.time-between-eviction-runs-millis=600

原創文章,作者:QYCUH,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/334644.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
QYCUH的頭像QYCUH
上一篇 2025-02-05 13:05
下一篇 2025-02-05 13:05

相關推薦

  • 從ga角度解讀springboot

    springboot作為目前廣受歡迎的Java開發框架,其中的ga機制在整個開發過程中起著至關重要的作用。 一、ga是什麼 ga即Group Artifacts的縮寫,它是Mave…

    編程 2025-04-29
  • SpringBoot Get方式請求傳參用法介紹

    本文將從以下多個方面對SpringBoot Get方式請求傳參做詳細的闡述,包括URL傳參、路徑傳參、請求頭傳參、請求體傳參等,幫助讀者更加深入地了解Get請求方式下傳參的相關知識…

    編程 2025-04-27
  • SpringBoot如何設置不輸出Info日誌

    本篇文章將帶您了解如何在SpringBoot項目中關閉Info級別日誌輸出。 一、為什麼要關閉Info日誌 在開發中,我們經常會使用Log4j、Logback等框架來輸出日誌信息,…

    編程 2025-04-27
  • 解決springboot中scanBasePackages無法讀取子包的問題

    在使用springboot搭建項目時,可能會遇到scanBasePackages無法讀取子包的問題。本文將從幾個方面詳細闡述如何解決這個問題。 一、問題描述 在使用Springbo…

    編程 2025-04-25
  • SpringBoot請求參數綁定

    解答:SpringBoot請求參數綁定是指將HTTP請求中的參數與Controller方法的參數綁定起來,使得參數的傳遞變得簡單和方便。下面我們將從多個方面對SpringBoot請…

    編程 2025-04-25
  • SpringBoot文件上傳詳解

    一、前言 隨著互聯網的發展,文件上傳成為了必備的功能之一,而SpringBoot作為目前最流行的開發框架之一,為文件上傳提供了便捷而強大的解決方案。 二、使用multipart/f…

    編程 2025-04-24
  • 使用SpringBoot開發高效的Web服務應用

    一、快速入門 SpringBoot可以讓你更快速地搭建Web應用,它為開發者提供了許多使用時省去了很多配置代碼的便利。在這裡,我們將通過一個簡單的示例來介紹如何使用SpringBo…

    編程 2025-04-24
  • 使用SpringBoot連接MySQL資料庫

    SpringBoot是一個用於構建基於Spring框架的應用程序的快速開發工具,它提供了許多函數和庫,使開發人員能夠快速構建應用程序並將其部署到雲中。同時,MySQL是一個流行的關…

    編程 2025-04-24
  • Nacos SpringBoot版本詳解

    一、Nacos簡介 Nacos是一個開源的分散式配置管理和服務發現平台,為微服務架構提供了基礎設施支持。它可以幫助開發人員解決微服務架構中的服務發現、服務配置、服務元數據管理和流量…

    編程 2025-04-23
  • SpringBoot的好處

    一、簡化開發流程 用SpringBoot開發項目可以大大減少繁瑣的配置工作,大部分的配置都是默認配置,只需要添加相應的依賴,即可完成開發工作。SpringBoot可以讓你更專註於業…

    編程 2025-04-23

發表回復

登錄後才能評論