如何自己实现多数据源

1、方向明确

拿我们最常用的mybatis来说,它获取数据库连接时就是通过获取DataSource对象的getConnection()方法来获取的,我们可以简单看一下mybatis的源码。当我们使用myabtis框架进行查询、修改操作时,它通过调用query、update等方法来操作数据库

query方法又调用了doQuery方法

而这个doQuery是调用子类SimpleExecutor中的方法

最终层层调用JdbcTransaction中的DataSource对象的getConnection方法

因此我们的方向很明确,只需要在它拿到连接的时候返回不同的DataSource对象就可以实现多数据源

2、实际操作

我们通过AOP实现在进入方法前切换到指定数据源,然后改写DataSource方法逻辑即可,可以让DataSource对象中的getConnection方法中进行处理,来获取方法指定的数据源

因此我们需要先定义一个线程上下文,这个上下文中需要记录我们在当前线程中需要使用的数据源

数据源配置

实现多数据源,必须要配置多数据源的连接信息,我们可以在配置文件中进行编写

DataSourceContextHolder

在这个上下文中,定义了三个方法,设置线程使用的数据源名称、获取、清空

方便我们后面在线程中设置和获取数据源名称

java 复制代码
public class DataSourceContextHolder {


    private static final ThreadLocal<String> DATA_SOURCE_THREAD_LOCAL = new ThreadLocal<>();


    public static void setDataSourceName(String dataSourceName)
    {
        DATA_SOURCE_THREAD_LOCAL.set(dataSourceName);
    }

    public static String getDataSourceName()
    {
        return DATA_SOURCE_THREAD_LOCAL.get();
    }


    public static void clearDataSourceName()
    {
        DATA_SOURCE_THREAD_LOCAL.remove();
    }
}

CustomDataSource

这个类需要继承Spring官方的AbstractRoutingDataSource来实现数据源的动态切换,我们需要重写里面的determineCurrentLookupKey方法,这个方法就是决定使用哪个数据源的key,然后调用父类的getConnection方法即可实现切换数据源

我们需要将本次的数据源信息告诉AbstractRoutingDataSource

所以我们需要返回线程上下文中的数据源名,和告诉当前项目中的数据源信息

上面定义了线程上下文,上下文中存的就是本次使用的数据源名

java 复制代码
public class CustomDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        // 返回本次线程中使用的数据源名称
        return DataSourceContextHolder.getDataSourceName();
    }

    public CustomDataSource(DataSource defaultTargetDataSource, Map<Object, Object> dataSourcesMap)
    {
        // 设置默认使用哪个数据源
        super.setDefaultTargetDataSource(defaultTargetDataSource);
        // 可以使用哪些数据源
        super.setTargetDataSources(dataSourcesMap);
        // 加载数据源
        super.afterPropertiesSet();
    }
}

DataSourceConfig

我们需要定义项目中可以使用的数据源,通过读取配置信息返回成DataSource对象,然后mybatis通过调用这个对象的getConnection方法来获取连接

复制代码
DataSourceProperties对象:数据源的基本信息,因为我们自己定义了两个,所以需要两个
java 复制代码
@Configuration
public class DataSourceConfig {

    // ===== DB1 配置属性 =====
    @Bean
    @ConfigurationProperties("spring.datasource.db1")
    public DataSourceProperties db1Properties() {
        return new DataSourceProperties();
    }

    // ===== DB1 数据源 =====
    @Bean
    public DataSource db1DataSource() {
        return db1Properties()
                .initializeDataSourceBuilder()
                .build();
    }

    // ===== DB2 配置属性 =====
    @Bean
    @ConfigurationProperties("spring.datasource.db2")
    public DataSourceProperties db2Properties() {
        return new DataSourceProperties();
    }

    // ===== DB2 数据源 =====
    @Bean
    public DataSource db2DataSource() {
        return db2Properties()
                .initializeDataSourceBuilder()
                .build();
    }


    @Bean(name = "customDataSource")
    @Primary // 重点:优先使用这个数据源
    public CustomDataSource dataSource(DataSource db1DataSource, DataSource db2DataSource)
    {
        Map<Object, Object> customDataSource = new HashMap<>();
        customDataSource.put("db1",db1DataSource);
        customDataSource.put("db2",db2DataSource);
        return new CustomDataSource(db1DataSource,customDataSource);
    }
}

必须给CustomDataSource添加@Primary表示优先使用这个数据源,然后就可以通过里面的CustomDataSource的父类进行切换

但现在就可以测试了

3、结果测试

我们写三个接口进行测试,分别查db1、db2、和不指定库

这里为了测试简单就不写AOP来处理了,后续可以自己加上

成功

当我们什么数据源都没指定,就走了默认的数据源

相关推荐
Baron X37 分钟前
Redis 7.0.9 完整部署指南
数据库·redis
weixin_4407305041 分钟前
数据库缓存、索引、缓存命中率的理解
数据库·缓存
DeepAgent1 小时前
AI Agent 工程实践(34):企业 AI Agent 架构
数据库·人工智能·agent
致Great2 小时前
Qwen3.8-Flash 发布:6B 激活,Qwen4 架构提前亮相
数据库·架构
张文君2 小时前
ubuntu26.04从ext4改成raid1+lvm启动
数据库·postgresql
鲨鱼辣钊2 小时前
FastAPI筑基_Day15_Alembic数据库迁移实战
数据库·elasticsearch·fastapi
叫我:松哥2 小时前
基于Flask的教师评教管理系统,支持学生和教师两种角色登录
数据库·后端·python·数据挖掘·flask
Tisfy3 小时前
LeetCode 3720.大于目标字符串的最小字典序排列:状态机 —— :从左往右枚举,失败则退回(最多退回一次)
linux·数据库·leetcode·字符串·状态机·构造
csdn_aspnet3 小时前
mysql 函数、存储过程写法及示例
数据库·mysql·存储过程·函数·function·procedure
IvorySQL3 小时前
倒计时 6 天!PGConf.Asia 2026 演讲征集即将截止
数据库·人工智能·postgresql