spring 多个数据库之间切换
多数据源问题很常见,例如读写分离数据库配置。
原来的项目出现了新需求,局方要求新增某服务器用以提供某代码,涉及到多数据源的问题。
研究成果如下:
1、首先配置多个datasource
- <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
- <property name="driverClassName" value="net.sourceforge.jtds.jdbc.Driver">
- </property>
- <property name="url" value="jdbc:jtds:sqlserver://10.82.81.51:1433;databaseName=standards">
- </property>
- <property name="username" value="youguess"></property>
- <property name="password" value="youguess"></property>
- </bean>
- <bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource">
- <property name="driverClassName" value="net.sourceforge.jtds.jdbc.Driver">
- </property>
- <property name="url" value="jdbc:jtds:sqlserver://10.82.81.52:1433;databaseName=standards">
- </property>
- <property name="username" value="youguess"></property>
- <property name="password" value="youguess"></property>
- </bean>
2、写一个DynamicDataSource类继承AbstractRoutingDataSource,并实现determineCurrentLookupKey方法
- package com.standard.core.util;
- import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
- public class DynamicDataSource extends AbstractRoutingDataSource {
- @Override
- protected Object determineCurrentLookupKey() {
- return CustomerContextHolder.getCustomerType();
- }
- }
3、利用ThreadLocal解决线程安全问题
- package com.standard.core.util;
- public class CustomerContextHolder {
- public static final String DATA_SOURCE_A = "dataSource";
- public static final String DATA_SOURCE_B = "dataSource2";
- private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
- public static void setCustomerType(String customerType) {
- contextHolder.set(customerType);
- }
- public static String getCustomerType() {
- return contextHolder.get();
- }
- public static void clearCustomerType() {
- contextHolder.remove();
- }
- }
4、数据源配置
- <bean id="dynamicDataSource" class="com.standard.core.util.DynamicDataSource" >
- <property name="targetDataSources">
- <map key-type="java.lang.String">
- <entry value-ref="dataSource" key="dataSource"></entry>
- <entry value-ref="dataSource2" key="dataSource2"></entry>
- </map>
- </property>
- <property name="defaultTargetDataSource" ref="dataSource" >
- </property>
- </bean>
5、在DAOImpl代码中手动切换数据源
- CustomerContextHolder.setCustomerType(CustomerContextHolder.DATA_SOURCE_B);
6、或者用AOP动态切换数据源
package datasource;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class DynamicDataSourceAspect {
@Pointcut("execution (public service.impl..*.*(..))")
public void serviceExecution(){}
@Before("serviceExecution()")
public void setDynamicDataSource(JoinPoint jp) {
for(Object o : jp.getArgs()) {
//处理具体的逻辑 ,根据具体的境况CustomerContextHolder.setCustomerType()选取DataSource
}
}
}
搞定!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?