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/n/334644.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
QYCUHQYCUH
上一篇 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

发表回复

登录后才能评论