【Spring-Data】JDBC

JDBC 多数据源实现

参考:https://cloud.tencent.com/developer/article/2186673

Springboot 中使用 JdbcTemplate 实现多数据源比较简单。查看 JdbcTemplate 源码;可以发现 JdbcTemplate 提供了传入 DataSource 的方式构建不同的 JdbcTemplate 实例。通过该方式就可以实现多数据源。

引入:spring-boot-starter-jdbc,mysql 的POM依赖

1、定义2个数据源的配置,前缀不同

2、定义 DataSourceConfig,实现2个DataSource bean(传入不同的@ConfigurationProperties(prefix=xxx)

3、定义 JdbcTemplateConfig,定义2个JdbcTemplate,传入不同的Datasource实例

4、定义不同的Repository,传入不同的JdbcTemplate

 

动态数据源切换

https://www.jianshu.com/p/a042ff2ee2ae

实现数据源切换的功能就是自定义一个类扩展AbstractRoutingDataSource抽象类,其实该相当于数据源DataSourcer的路由中介,可以实现在项目运行时根据相应key值切换到对应的数据源DataSource上。

方法里使用到了determineCurrentLookupKey()方法,它是AbstractRoutingDataSource类的抽象方法,也是实现数据源切换要扩展的方法,该方法的返回值就是项目中所要用的DataSource的key值,拿到该key后就可以在resolvedDataSource中取出对应的DataSource,如果key找不到对应的DataSource就使用默认的数据源。

AbstractRoutingDatasource

参考:https://www.baeldung.com/spring-abstract-routing-data-source

1、Datasource Context

AbstractRoutingDatasource requires information to know which actual DataSource to route to. This information is typically referred to as Context.

2、Context Holder

It’s critically important to use ThreadLocal here so that the context is bound to the currently executing thread.

public class ClientDatabaseContextHolder {
    private static ThreadLocal<ClientDatabase> CONTEXT  = new ThreadLocal<>();
    public static void set(ClientDatabase clientDatabase) {
        Assert.notNull(clientDatabase, "clientDatabase cannot be null");
        CONTEXT.set(clientDatabase);
    }
    public static ClientDatabase getClientDatabase() {
        return CONTEXT.get();
    }
    public static void clear() {
        CONTEXT.remove();
    }
}

3、Datasource Router

We define our ClientDataSourceRouter to extend the Spring AbstractRoutingDataSource. We implement the necessary determineCurrentLookupKey method to query our ClientDatabaseContextHolder and return the appropriate key.

The AbstractRoutingDataSource implementation handles the rest of the work for us and transparently returns the appropriate DataSource:

public class ClientDataSourceRouter extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return ClientDatabaseContextHolder.getClientDatabase();
    }
}

4、

We need a Map of contexts to DataSource objects to configure our AbstractRoutingDataSource. We can also specify a default DataSource if there is no context set.

The DataSources we use can come from anywhere but will typically be either created at runtime or looked up using JNDI:

@Configuration
public class RoutingTestConfiguration {
    @Bean
    public ClientService clientService() {
        return new ClientService(new ClientDao(clientDatasource()));
    }
    @Bean
    public DataSource clientDatasource() {
        Map<Object, Object> targetDataSources = new HashMap<>();
        DataSource clientADatasource = clientADatasource();
        DataSource clientBDatasource = clientBDatasource();
        targetDataSources.put(ClientDatabase.CLIENT_A, clientADatasource);
        targetDataSources.put(ClientDatabase.CLIENT_B, clientBDatasource);

        ClientDataSourceRouter clientRoutingDatasource = new ClientDataSourceRouter();
        clientRoutingDatasource.setTargetDataSources(targetDataSources);
        clientRoutingDatasource.setDefaultTargetDataSource(clientADatasource);
        return clientRoutingDatasource;
    }
}

5、定义2个不同的datasource,参考文章顶部的类似定义

 

posted @ 2024-09-05 11:23  飞翔在天  阅读(41)  评论(0)    收藏  举报