SpringBoot多数据源读写分离的自定义配置问题及解决方法

yizhihongxing
  1. 背景介绍

Spring Boot 是一种基于 Spring 框架的快速开发 Web 应用的微服务框架,它的设计能够使开发者极速创建可独立运行的 Spring 应用程序。而在实际的开发过程中,很多业务场景需要使用多个数据源,并且多个数据源的读写分离也是一种非常常见的数据存储方案,这时候就需要对 Spring Boot 进行多数据源配置。

  1. Spring Boot 多数据源配置

在 Spring Boot 中实现多数据源配置可以通过以下步骤:

(1)引入相关依赖。

<!--mysql-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.21</version>
</dependency>
<!--Druid连接池-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.5</version>
</dependency>

(2)在 application.yml 文件中进行数据源配置。

spring:
  datasource:
    master:
      url: jdbc:mysql://localhost:3306/test?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8
      username: root
      password: root
      driver-class-name: com.mysql.cj.jdbc.Driver
    slave1:
      url: jdbc:mysql://localhost:3307/test?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8
      username: root
      password: root
      driver-class-name: com.mysql.cj.jdbc.Driver

(3)自定义多数据源配置类。

@Configuration
public class DataSourceConfig {
    @Bean(name = "masterDataSource")
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource.master")
    public DruidDataSource masterDataSource() {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean(name = "slaveDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.slave1")
    public DruidDataSource slaveDataSource() {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean(name = "dynamicDataSource")
    @Primary
    public DynamicDataSource dynamicDataSource(@Qualifier("masterDataSource") DataSource masterDataSource,
                                               @Qualifier("slaveDataSource") DataSource slaveDataSource) {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DataSourceType.MASTER.getType(), masterDataSource);
        targetDataSources.put(DataSourceType.SLAVE.getType(), slaveDataSource);

        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        dynamicDataSource.setDefaultTargetDataSource(masterDataSource); //默认数据源
        dynamicDataSource.setTargetDataSources(targetDataSources);

        return dynamicDataSource;
    }
}

(4)自定义数据源持有类。

public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceHolder.getDataSource();
    }
}

(5)定义数据源类型枚举类。

public enum DataSourceType {
    MASTER("master"),
    SLAVE("slave");

    private String type;

    DataSourceType(String type) {
        this.type = type;
    }

    public String getType() {
        return type;
    }
}

(6)定义数据源 Holder 类,用于在线程中存储数据源类型的信息。

public class DataSourceHolder {
    /**
     * 使用ThreadLocal将数据源与当前线程绑定
     */
    private static final ThreadLocal<String> holder = new ThreadLocal<>();

    /**
     * 绑定数据源
     */
    public static void putDataSource(String dataSource) {
        holder.set(dataSource);
    }

    /**
     * 获取当前绑定的数据源
     */
    public static String getDataSource() {
        return holder.get();
    }

    /**
     * 清除绑定的数据源信息
     */
    public static void clear() {
        holder.remove();
    }
}

(7)在 Service 层的方法上加上数据源注解,注明该方法使用哪个数据源。

@Service
@Slf4j
public class UserInfoServiceImpl implements UserInfoService {

    @Autowired
    private UserInfoMapper userInfoMapper;

    /**
     * 使用主库进行写操作
     */
    @DataSource(value = DataSourceType.MASTER)
    @Override
    public int addUserInfo(UserInfo userInfo) {
        return userInfoMapper.insertSelective(userInfo);
    }

    /**
     * 使用从库进行读操作
     */
    @DataSource(value = DataSourceType.SLAVE)
    @Override
    public UserInfo getUserInfoById(String id) {
        return userInfoMapper.selectByPrimaryKey(id);
    }
}
  1. 示例说明

以下是两个示例,分别是对主库进行写操作和对从库进行读操作。

(1)向主库中插入一条用户信息。

@PostMapping("/addUser")
public String addUser(@RequestBody UserInfo userInfo) {
    try {
        userInfoService.addUserInfo(userInfo);
        return "添加成功!";
    } catch (Exception e) {
        e.printStackTrace();
        return "添加失败!";
    }
}

(2)从从库中查询一条用户信息。

@GetMapping("/getUser/{id}")
public UserInfo getUser(@PathVariable("id") String id) {
    try {
        return userInfoService.getUserInfoById(id);
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}
  1. 总结

通过以上步骤,我们即可轻松地实现 Spring Boot 的多数据源配置,实现读写分离,提高系统的并发能力和稳定性。需要注意的是,在实际的开发中,我们还需考虑到数据源的负载均衡、事务管理、多数据源切换等问题,需要在实际的生产环境中根据需求进行进一步的配置和调整。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringBoot多数据源读写分离的自定义配置问题及解决方法 - Python技术站

(0)
上一篇 2023年5月18日
下一篇 2023年5月18日

相关文章

  • 详解Mysql中日期比较大小的方法

    下面是详解Mysql中日期比较大小的方法的完整攻略。 1. 比较两个日期大小的方法 在Mysql中,比较两个日期的大小可以使用大于号(>),小于号(<),等于号(=)进行比较。 假设我们有一个表格orders,我们要查询出日期大于2020年1月1日的订单,可以使用如下SQL语句: SELECT * FROM orders WHERE order_…

    database 2023年5月22日
    00
  • 如何使用Python实现数据库中数据的批量拆分合并?

    以下是使用Python实现数据库中数据的批量拆分合并的完整攻略。 数据库中数据的批量拆分合并简介 在数据库中,批量拆合并是将多记录拆分成多个记录或将多个记录合并成一个记录。在Python中,可以使用pymysql连接MySQL,并使用SELECT和INSERT`语句实现批量拆分合并。 步骤1:连接数据库 在Python中,可以使用pymysql连接MySQL…

    python 2023年5月12日
    00
  • Mysql数据库存储过程基本语法讲解

    Mysql数据库存储过程基本语法讲解 存储过程是一种预编译的代码块,可以在MySQL数据库中创建和使用。它们是一些SQL语句的集合,可以在一起执行特定的任务。在存储过程中,可以定义变量、使用分支语句、循环语句等,从而实现复杂的业务逻辑。下面将介绍存储过程的基本语法。 创建存储过程 创建存储过程的语法如下: CREATE PROCEDURE procedure…

    database 2023年5月22日
    00
  • Linux下用Nginx作Perl程序服务器及其中Perl模块的配置

    下面为您详细讲解“Linux下用Nginx作Perl程序服务器及其中Perl模块的配置”的完整攻略。 概述 使用 Nginx 作为 Perl 程序服务器,可以极大地提高服务器的效率和稳定性。同时,也可以使用 Perl 模块来增强 Perl 程序的成功率和有效性。 安装Nginx 首先,需要先安装 Nginx。使用命令行工具输入以下命令: $ sudo apt…

    database 2023年5月22日
    00
  • 命令行启动mssqlserver服务的方法示例

    下面是详细讲解“命令行启动mssqlserver服务的方法示例”的完整攻略: 命令行启动mssqlserver服务的方法示例 简介 MSSQL Server是一款广泛使用的关系型数据库管理系统,MSSQL Server的服务启动方式有多种,其中通过命令行启动服务是一种常见的方式。 步骤 打开命令行终端 通常可以通过在Windows系统中按下“Win+R”快捷…

    database 2023年5月22日
    00
  • MySQL Select语句是如何执行的

    MySQL Select语句是一种用于从数据库中检索数据的SQL语句。它的执行过程包含以下几个步骤: ① 语法分析:MySQL会先对Select语句进行语法分析,确保它符合SQL的语法规范和要求。 ② 查询优化器:MySQL会对Select语句进行优化,以提高执行效率。它会决定执行策略、优化器的使用和数据源的选择等等。其中,优化器是一个重要的组件,它可以尝试…

    database 2023年5月22日
    00
  • nodeJS与MySQL实现分页数据以及倒序数据

    实现分页和倒序查询数据是开发Web应用的常见需求。本文将介绍如何使用Node.js和MySQL实现分页数据和倒序数据的查询。 准备工作 在继续之前,你需要确保安装了以下软件: Node.js MySQL 你还需要使用npm来安装以下Node.js包: mysql:以Node.js方式访问MySQL数据库。 express:用于创建Web应用程序的框架。 np…

    database 2023年5月21日
    00
  • MySQL数据类型和常用字段属性总结

    MySQL数据类型和常用字段属性总结 MySQL是目前使用最广泛的关系型数据库之一,不同于其他类型数据库的是,MySQL具有非常丰富的数据类型和字段属性。 数据类型 整型 MySQL定义了5种不同长度的整型,分别为:TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT。这些整型可以用来存储整数值,具体范围和存储大小如下所示: 类型 存储…

    database 2023年5月22日
    00
合作推广
合作推广
分享本页
返回顶部