springbootalreadyjava学习之路

Spring Boot多数据源切换查询

2022-10-26  本文已影响0人  唯有努力不欺人丶

今天遇到一个场景,公司的消息因为过多。所以做成了分库的情况。一个月内的数据存在当前表中。一个月之前的数据存放在备份表中。然后把主库和备份库做成多数据源的形式。在查询的时候如果主库表中没有就去备份库中查询。
其实说起来好像挺高端的。但是实现上很简单,下面是具体的实现。

数据源配置

导包,基本项目架构啥的我就不多说了。直接上配置文件。我这里是用yml的形式:

spring:
  datasource:
    # Druid数据库连接池
    type: com.alibaba.druid.pool.DruidDataSource
    url: jdbc:clickhouse://xxx:8123/test
    driverClassName: com.clickhouse.jdbc.ClickHouseDriver
    druid:
      first:  # 数据源1
        # 数据库驱动
        driver-class-name: com.clickhouse.jdbc.ClickHouseDriver
        url: jdbc:clickhouse://xxx:8123/test
        username: default
        password: default
      second:  # 数据源2
        # 数据库驱动
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://xxx:3306/test?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone= GMT%2B8
        username: root
        password: 123456
      third:  # 数据源3
        # 数据库驱动
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://xxx:3306/test?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone= GMT%2B8
        username: root
        password: 123456
      fourth:  # 数据源3
        # 数据库驱动
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://XXX:3306/test_b?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false
        username: root
        password: 123456
      initial-size: 10
      max-active: 100
      min-idle: 10
      max-wait: 60000

这里所有关于数据库地址和名称我都隐藏了,要根据具体的情况配置。但是如图所示,我们这里配置了四个数据源。第一个是个clickhouse数据库,二三四都是mysql。其中第三个是我说到的消息的主库,第四个是我说的消息的历史库。

sql配置

    @DataSource(name = DataSourceNames.THIRD)
    Integer if_exist(Map<String, Object> params);

    @DataSource(name = DataSourceNames.FOURTH)
    Integer if_exist_archive(Map<String, Object> params);

    @DataSource(name = DataSourceNames.THIRD)
    Map<String, Object> preview(Map<String, Object> params);

    @DataSource(name = DataSourceNames.FOURTH)
    Map<String, Object> preview_archive(Map<String, Object> params);

注意看上面的代码,第一个方法if_exist 指定的是第三个数据源,我上面说过是消息表的主库。if_exist_archive指定的是第四个数据源,也就是消息表的历史库。
同理下面的两个查询数据的方法一个是主库查询,一个是历史库查询。
sql其实就是很无脑的一个判断是否存在,一个查询数据。

    <select id="if_exist" parameterType="map" resultType="int">
        SELECT EXISTS(SELECT 1
        FROM msg AS b
        WHERE FileName = #{filename}
        LIMIT 1)
    </select>

    <select id="if_exist_archive" parameterType="map" resultType="int">
        SELECT EXISTS(SELECT 1
        FROM msg AS b
        WHERE FileName = #{filename}
        LIMIT 1)
    </select>

    <select id="preview" parameterType="map" resultType="map">
        SELECT
            uncompress(b.Message) AS Message
        FROM msg AS b
        WHERE FileName = #{filename}
        LIMIT 1
    </select>
    
    <select id="preview_archive" parameterType="map" resultType="map">
        SELECT
        uncompress(b.Message) AS Message
        FROM msg AS b
        WHERE FileName = #{filename}
        LIMIT 1
    </select>

代码维护切换数据库

上面我们数据源,sql都配置好了。接下来就是代码维护了。理论上就是主库查不到就去历史库查询,使用方法如下:

        Map<String, Object> result;

        if (msgDao.if_exist(params) > 0) {
            result = msgDao.preview(params);
        } else {
            result = msgDao.preview_archive(params);
        };

就这么几行代码就实现了这个功能。

结语

其实这个功能我感觉是会则不难,难则不会。
看到了人家的做法之后恍然大悟,觉得简单的很。可是在这之前我是没有这种类似的想法的。甚至说之前的做法都局限于一个数据库,最多就是分表而已。写起来也没这么简单。两张表需要两个entity和Dao甚至xml。总而言之又学到了一种用法,还是挺开心的。
本篇笔记就记到这里,如果稍微帮到你了记得点个喜欢点个关注,也祝大家工作顺顺利利,每天学习一点点~

上一篇下一篇

猜你喜欢

热点阅读