1.使用
1)写一个DynamicDataSource类继承AbstractRoutingDataSource
public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DSNameHolder.getDSName(); } /** * used for test * @return */ public DataSource getCurrentDataSource() { return super.determineTargetDataSource(); } }
2) DSNameHolder
public class DSNameHolder { public static ThreadLocal<String> DS_NAME_HOLDER = new ThreadLocal<String>(); public static void setDSName(String dsName) { DS_NAME_HOLDER.set(dsName); } public static String getDSName() { return DS_NAME_HOLDER.get(); } }
3)测试
spring-ds.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean name="datasource" class="com.siyuan.study.spring.jdbc.DynamicDataSource"> <property name="targetDataSources"> <map> <entry key="ds_a" value-ref="datasource_a"/> <entry key="ds_b" value-ref="datasource_b"/> </map> </property> <property name="defaultTargetDataSource" ref="datasource_a"/> </bean> <bean id="datasource_a" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="url" value="jdbc:mysql://localhost:3306;databaseName=test_a" /> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="username" value="root" /> <property name="password" value="123456" /> </bean> <bean id="datasource_b" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="url" value="jdbc:mysql://localhost:3306;databaseName=test_b" /> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="username" value="root" /> <property name="password" value="123456" /> </bean> </beans>
DynamicDataSourceTest
public class DynamicDataSourceTest { private ApplicationContext ctxt; @Before public void setup() { ctxt = new ClassPathXmlApplicationContext("spring-ds.xml"); } @Test public void getConnection() { DynamicDataSource datasource = (DynamicDataSource) ctxt.getBean("datasource"); DataSource datasource_a = (DataSource) ctxt.getBean("datasource_a"); DataSource datasource_b = (DataSource) ctxt.getBean("datasource_b"); assertSame(datasource_a, datasource.getCurrentDataSource()); //switch to ds_b DSNameHolder.setDSName("ds_b"); assertSame(datasource_b, datasource.getCurrentDataSource()); //switch to ds_a DSNameHolder.setDSName("ds_a"); assertSame(datasource_a, datasource.getCurrentDataSource()); } }
2.源码分析
1)afterPropertiesSet
public void afterPropertiesSet() { if (this.targetDataSources == null) { throw new IllegalArgumentException("Property 'targetDataSources' is required"); } this.resolvedDataSources = new HashMap<Object, DataSource>(this.targetDataSources.size()); for (Map.Entry entry : this.targetDataSources.entrySet()) { Object lookupKey = resolveSpecifiedLookupKey(entry.getKey()); DataSource dataSource = resolveSpecifiedDataSource(entry.getValue()); this.resolvedDataSources.put(lookupKey, dataSource); } if (this.defaultTargetDataSource != null) { this.resolvedDefaultDataSource = resolveSpecifiedDataSource(this.defaultTargetDataSource); } }
2)getConnection
public Connection getConnection() throws SQLException { return determineTargetDataSource().getConnection(); } public Connection getConnection(String username, String password) throws SQLException { return determineTargetDataSource().getConnection(username, password); }
3)determineTargetDataSource
protected DataSource determineTargetDataSource() { Assert.notNull(this.resolvedDataSources, "DataSource router not initialized"); Object lookupKey = determineCurrentLookupKey(); DataSource dataSource = this.resolvedDataSources.get(lookupKey); if (dataSource == null && (this.lenientFallback || lookupKey == null)) { dataSource = this.resolvedDefaultDataSource; } if (dataSource == null) { throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]"); } return dataSource; }
3.参考资料
http://blog.163.com/wang_hj138@126/blog/static/140800106201263151242338/
http://www.360doc.com/content/13/1016/15/14212114_321868950.shtml
相关推荐
在本项目中,我们将探讨如何利用MyBatis与Spring框架实现动态切换数据源的功能。首先,我们需要理解MyBatis和Spring的基本概念以及它们如何协同工作。 MyBatis是一个优秀的持久层框架,它简化了Java与数据库之间的...
本项目“Spring+SpringMvc+MybatisPlus+Aop(自定义注解)动态切换数据源”正是针对这一需求提供的一种解决方案。下面将详细介绍这个项目中的关键技术点和实现原理。 首先,Spring框架是Java企业级应用开发的核心...
总结来说,动态切换数据源是大型分布式系统中不可或缺的功能,通过Spring的`AbstractRoutingDataSource`和适当的配置,我们可以轻松地在SSM框架下实现这一功能,从而更好地管理和扩展我们的应用程序。
springboot+mybatis+mysql+AbstractRoutingDataSource实现多数据源切换(一写多读数据源)项目中包含完整的demo案例配备文档说明,亲测可用;实现简单,代码思路清晰.
【Spring 动态数据源切换】使用 `AbstractRoutingDataSource` 的详细实现在处理多数据库环境时,Spring 提供了一个强大的工具 `AbstractRoutingDataSource`,它允许我们根据特定条件动态地切换数据源。本文将深入...
动态数据源是指在运行时能够根据业务逻辑或用户需求动态地选择和切换数据源的技术。在SpringBoot中,我们可以利用`AbstractRoutingDataSource`来实现这一功能。`AbstractRoutingDataSource`是Spring提供的一个抽象类...
在Spring Boot应用中,动态切换数据源是一项关键功能,尤其在多数据库环境或者读写分离的架构中。这里我们将深入探讨如何使用`ThreadLocal`和`AbstractRoutingDataSource`来实现这一目标。 `ThreadLocal`是Java提供...
SpringBoot2.x 继承 AbstractRoutingDataSource 动态数据源切换实现 JPA读写分离。 使用MyCat代理MySQL8数据库,添加root账户(读写)和user账户(只读)模拟读写简单分离。
本主题将深入探讨如何利用SpringBoot结合Atomikos实现动态多数据源以及事务管理,并介绍两种切换数据源的方法。 首先,SpringBoot简化了传统Spring应用的初始化过程,它通过自动配置和starter包让开发者快速搭建...
SSH动态切换数据源是一种在Java Web开发中处理多数据库连接切换的技术,主要应用于Spring、Struts和Hibernate(SSH)这三大框架集成的项目。SSH框架是企业级应用开发的常用组合,提供了强大的业务逻辑处理和数据持久...
此外,为了在代码中切换数据源,通常会有一个数据源路由的策略,例如在Service层根据业务逻辑决定使用哪个数据源。这可能涉及到AOP(面向切面编程)的使用,通过注解或配置来切换数据源。 在实际开发中,多数据源的...
动态创建和切换数据源是一项重要的技能,尤其是在大型企业级应用或分布式系统中,它能够灵活地管理多个数据库,提高系统的可扩展性和适应性。以下是对这个主题的详细阐述: 1. **什么是数据源**:数据源...
动态切换数据源意味着程序可以根据运行时的需求,灵活地选择要使用的数据源。这对于处理复杂业务逻辑和优化系统性能至关重要。例如,读操作可能指向一个只读的数据源,而写操作则连接到主数据库。 4. **实现方式**...
在现代企业级应用开发...总的来说,Spring Boot结合JPA或MyBatis实现多数据源动态切换,不仅提高了系统的灵活性,还便于进行数据库扩展和管理。理解和掌握这一技术,对于提升系统设计能力和解决复杂问题具有重要意义。
这样,我们可以在运行时根据业务需求灵活地切换数据源。 6. **分布式事务控制** AtomikosDataSource支持JTA事务,这意味着我们可以在同一个事务中操作多个数据源。Spring的`@Transactional`注解可以用来开启和管理...
在Java的Spring框架中,动态切换数据源是一项重要的功能,尤其在多租户、微服务或者需要根据业务逻辑切换数据库的场景下。本知识点主要围绕如何在Spring中实现数据源的动态切换进行深入探讨。 首先,我们需要理解...
本项目“spring 3.29+struts2.3.15.1+hibernate3 动态切换数据源”正是针对这一需求,通过整合Spring、Struts2和Hibernate3这三大经典Java EE框架,实现了数据源的灵活配置和动态切换。 首先,Spring作为Java应用中...
综上所述,Spring动态切换数据源是通过配置不同数据源,结合`AbstractRoutingDataSource`子类和`ThreadLocal`管理的策略,实现在运行时选择合适的数据源执行SQL操作。这一机制极大地增强了系统的灵活性和可扩展性。
本文将深入探讨“真正意义的Spring动态切换数据源”这一主题,并结合源码进行分析。 动态数据源切换是在多数据库环境下的常见需求,例如在测试和生产环境中使用不同的数据库,或者在微服务架构中,每个服务可能需要...
本示例代码着重讲解如何在Java环境中实现分库操作,包括备份库、建库以及动态创建和切换数据源。下面我们将深入探讨这些知识点。 首先,我们来理解"分库"的概念。当业务数据量增大,单一数据库无法有效支撑时,我们...