如何自己实现多数据源

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来处理了,后续可以自己加上

成功

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

相关推荐
maqr_11021 小时前
MySQL数据库迁移到云端如何保障安全_数据加密与SSL连接配置
jvm·数据库·python
u01091476021 小时前
MySQL如何限制触发器递归调用的深度_防止触发器死循环方法
jvm·数据库·python
weixin_3812881821 小时前
MySQL中如何使用HEX函数转换十六进制_MySQL进制转换函数
jvm·数据库·python
Deitymoon21 小时前
嵌入式数据库——SQLite基础
数据库·sqlite
YMatrix 官方技术社区21 小时前
美国·硅谷|YMatrix 即将亮相 Postgres Conference 2026,前瞻 AI 时代的数据基座
数据库·数据仓库·postgresql·时序数据库·ymatrix
bKYP953cL21 小时前
构建自己的AI编程助手:基于RAG的上下文感知实现方案
数据库·人工智能·ai编程
Bert.Cai21 小时前
MySQL DML简介
数据库·mysql
maqr_11021 小时前
HTML怎么生成订单预览_HTML只读订单信息结构【操作】
jvm·数据库·python
2301_803875611 天前
如何通过phpMyAdmin给WordPress所有用户发送全站通知_系统表插入
jvm·数据库·python
2301_777599371 天前
mysql如何进行数据库容量规划_评估磁盘空间增长趋势
jvm·数据库·python