【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,参考文章顶部的类似定义
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)