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

  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日

相关文章

  • 一个多表查询的SQL语句

    下面是详细讲解“一个多表查询的SQL语句”的完整攻略。 完整攻略 Step 1:确定数据表的关系 在进行多表查询之前,我们需要先确定所涉及的数据表之间的关系,即它们之间的连接方式。 常见的数据表连接方式有以下三种: 内连接(INNER JOIN):返回匹配两个表中指定列并且存在于两个表中的行。 外连接(OUTER JOIN):返回匹配两个表中指定列的所有行,…

    database 2023年5月21日
    00
  • php读取mssql的ntext字段返回值为空的解决方法

    来讲解一下“php读取 mssql 的 ntext 字段返回值为空的解决方法”。 首先,我们需要了解一下这个问题的原因。在 MSSQL 中, ntext 字段是一种 Unicode 字符集,而 PHP 默认是使用 ANSI 字符集进行连接的,导致读取 ntext 类型字段时出现空值。解决这个问题的方法是将 PHP 的连接方式转换为 Unicode 码,这样就…

    database 2023年5月22日
    00
  • mysql中json_remove函数的使用?

    需求描述:   今天看json记录,可以通过json_remove函数对一个key或多个key从个json记录中去掉. 操作过程: 1.查看一个已经存在的json表 mysql> select * from tab_json; +—-+———————————————————…

    MySQL 2023年4月13日
    00
  • SpringBoot整合Graylog做日志收集实现过程

    SpringBoot整合Graylog做日志收集实现过程 Graylog是一款开源的日志收集、管理和分析平台。它能够集中管理来自不同来源的日志,支持灵活的日志搜索和高效的日志分析、可视化等功能。下面是SpringBoot整合Graylog做日志收集的实现过程: 步骤一:在Graylog中创建GELF输入 首先,我们需要在Graylog中创建一个GELF输入,…

    database 2023年5月22日
    00
  • MySQL与PHP的基础与应用专题之创建数据库表

    创建MySQL数据库表的步骤如下: 1. 登录MySQL服务 使用如下命令登录MySQL服务: mysql -u root -p 其中,”root”是MySQL服务的用户名。 2. 选择数据库 使用USE命令选择数据库。例如: USE mydatabase; 其中,”mydatabase”是要选择的数据库名。 3. 创建数据表 使用CREATE TABLE命…

    database 2023年5月22日
    00
  • Mysql元数据如何生成Hive建表语句注释脚本详解

    这里提供了一个Python脚本用来生成Hive建表语句的注释,该注释包括了Mysql元数据的信息。 准备工作 在使用该脚本前,需要先安装两个Python库pymysql和pandas。可以通过以下命令安装: pip install pymysql pandas 同时,在使用该脚本的时候,需要先获取数据库的元数据信息,例如表名、字段名、字段类型、注释等信息。 …

    database 2023年5月21日
    00
  • PHP 使用MySQL管理Session的回调函数详解

    PHP 使用MySQL管理Session的回调函数可以让我们更加灵活地控制Session,可以传入自己的回调函数来实现Session数据的持久化到MySQL数据库中,下面是详细的攻略: 准备工作 在使用这个技术之前,我们需要确保自己已经正确设置好PHP和MySQL的环境。在这里,假设您已经知道如何使用PHP和MySQL,并且已经创建好了一个名为user_in…

    database 2023年5月21日
    00
  • RabbitMQ与Redis队列对比

    本文仅针对RabbitMQ与Redis做队列应用时的情况进行对比具体采用什么方式实现,还需要取决于系统的实际需求 简要介绍 RabbitMQ RabbitMQ是实现AMQP(高级消息队列协议)的消息中间件的一种,最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。消息中间件主要用于组件之间的解耦,消息的发送者无需知道…

    Redis 2023年4月11日
    00
合作推广
合作推广
分享本页
返回顶部