`

Spring动态数据源路由实现

阅读更多
简单的翻译, 也算是一篇笔记.
原文:http://blog.springsource.com/2007/01/23/dynamic-datasource-routing/
在Spring 2.0.1中引入了AbstractRoutingDataSource, 该类充当了DataSource的路由中介, 能有在运行时, 根据某种key值来动态切换到真正的DataSource上, 同时对于不支持事务隔离级别的JTA事务来说, Spring还提供了另外一个类IsolationLevelDataSourceRouter来处理这个问题. 下面的例子将通过context来切换不同的数据源.
首先定义一个Catalog的Dao:
 package blog.datasource;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcDaoSupport;

public class Catalog extends SimpleJdbcDaoSupport {
        
   public List<Item> getItems() {
      String query = "select name, price from item";
      return getSimpleJdbcTemplate().query(query, new ParameterizedRowMapper<Item>() {
            public Item mapRow(ResultSet rs, int row) throws SQLException {
               String name = rs.getString(1);
               double price = rs.getDouble(2);
               return new Item(name, price);
            }
      });
   }
}


然后定义一个Item的JavaBean
package blog.datasource;

public class Item {

   private String name;
   private double price;
        
   public Item(String name, double price) {
      this.name = name;
      this.price = price;
   }

   public String getName() {
      return name;
   }

   public double getPrice() {
      return price;
   }

   public String toString() {
      return name + " (" + price + ")";
   }

}


接着定义一个枚举类型, 用来表示不同的用户级别, 通过该类型将映射到不同的数据源
public enum CustomerType {
   BRONZE, 
   SILVER, 
   GOLD
}


下面是DataSource定义:
<bean id="parentDataSource"
         class="org.springframework.jdbc.datasource.DriverManagerDataSource"
         abstract="true">
   <property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
   <property name="username" value="sa"/>
</bean>
                
<bean id="goldDataSource" parent="parentDataSource">
   <property name="url" value="jdbc:hsqldb:hsql://localhost:${db.port.gold}/blog"/>
</bean>

<bean id="silverDataSource" parent="parentDataSource">
   <property name="url" value="jdbc:hsqldb:hsql://localhost:${db.port.silver}/blog"/>
</bean>

<bean id="bronzeDataSource" parent="parentDataSource">
   <property name="url" value="jdbc:hsqldb:hsql://localhost:${db.port.bronze}/blog"/>
</bean>

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
   <property name="location" value="classpath:/blog/datasource/db.properties"/>
</bean>


AbstractRoutingDataSource 实现类
package blog.datasource;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class CustomerRoutingDataSource extends AbstractRoutingDataSource {

   @Override
   protected Object determineCurrentLookupKey() {
      return CustomerContextHolder.getCustomerType();
   }
}


CustomerContextHolder 是一个和LocalThread绑定的类, 定义如下:
public class CustomerContextHolder {

   private static final ThreadLocal<CustomerType> contextHolder = 
            new ThreadLocal<CustomerType>();
        
   public static void setCustomerType(CustomerType customerType) {
      Assert.notNull(customerType, "customerType cannot be null");
      contextHolder.set(customerType);
   }

   public static CustomerType getCustomerType() {
      return (CustomerType) contextHolder.get();
   }

   public static void clearCustomerType() {
      contextHolder.remove();
   }
}


将dao bean和datasource bean结合起来, 至于dao和真正的datasource如何关联这个可以根据需要指定相关的策略和规则来实现:
<bean id="catalog" class="blog.datasource.Catalog">
   <property name="dataSource" ref="dataSource"/>
</bean>

<bean id="dataSource" class="blog.datasource.CustomerRoutingDataSource">
   <property name="targetDataSources">
      <map key-type="blog.datasource.CustomerType">
         <entry key="GOLD" value-ref="goldDataSource"/>
         <entry key="SILVER" value-ref="silverDataSource"/>
      </map>
   </property>
   <property name="defaultTargetDataSource" ref="bronzeDataSource"/>
</bean>

下面通过一个TestCase来看看如何使用:
public class CatalogTests extends AbstractDependencyInjectionSpringContextTests {

   private Catalog catalog;

   public void setCatalog(Catalog catalog) {
      this.catalog = catalog;
   }

   public void testDataSourceRouting() {
      CustomerContextHolder.setCustomerType(CustomerType.GOLD);
      List<Item> goldItems = catalog.getItems();
      assertEquals(3, goldItems.size());
      System.out.println("gold items: " + goldItems);

      CustomerContextHolder.setCustomerType(CustomerType.SILVER);
      List<Item> silverItems = catalog.getItems();
      assertEquals(2, silverItems.size());
      System.out.println("silver items: " + silverItems);
        
      CustomerContextHolder.clearCustomerType();
      List<Item> bronzeItems = catalog.getItems();
      assertEquals(1, bronzeItems.size());
      System.out.println("bronze items: " + bronzeItems);              
   }

   protected String[] getConfigLocations() {
      return new String[] {"/blog/datasource/beans.xml"};
   }    
}
9
1
分享到:
评论
6 楼 liu4187915336 2016-04-26  
启动的时候报return (CustomerType) contextHolder.get(); 空指针,get()得到为null,怎么回事
5 楼 fisher 2015-07-07  
hbzyb 写道
并发会不会有什么问题呀?
并发应该会有问题,我在找解决办法找了好久。。。。。。。
4 楼 vi19900926 2012-04-22  
JTA事务不支持隔离级别吗?
3 楼 pn2008 2012-02-03  
如果要在service的一个方法里同时修改多数据源里的数据会出错,数据源并没有转换
2 楼 hbzyb 2011-08-16  
并发会不会有什么问题呀?
1 楼 weiqiulai 2010-12-15  
如果是不同的数据库如:mysql、mssql,hibernate sessionFactory如何配置呢?是不是只能配置两套了?

相关推荐

    spring动态数据源+mybatis分库分表

    在"spring-routing-datasource"这个文件中,可能包含了实现Spring动态数据源的示例代码,包括配置文件、路由数据源的实现以及与MyBatis的集成。通过研究这个例子,你可以更深入地理解如何在实际项目中部署和使用这种...

    动态数据源实现spring

    在Spring框架中,动态数据源实现是一个重要的特性,它允许应用程序根据特定的条件或用户需求在运行时切换数据源。这种灵活性对于多租户系统、数据隔离或者在不同环境(如开发、测试、生产)之间切换数据库配置尤其...

    真正意义的spring动态切换数据源源码

    这个抽象类维护了一个数据源路由决策表,可以根据特定的规则(如事务上下文、线程局部变量等)来决定使用哪个数据源。开发者需要继承这个类并实现`determineCurrentLookupKey()`方法,该方法返回一个键,该键对应于...

    spring动态选择数据源

    2. **数据源路由**: 在`AbstractRoutingDataSource`中,你需要实现数据源路由的逻辑。例如,你可以基于事务属性、请求上下文或其他自定义条件来决定使用哪个数据源。 3. **配置与注册**: 创建自定义的`...

    spring 动态多数据源配置代码

    - `AbstractRoutingDataSource`:这是Spring提供的核心类,用于动态路由数据源。它会根据某种策略(如事务ID、特定的标记等)决定使用哪个数据源。 - `DataSourceTransactionManager`:为每个数据源提供事务管理器...

    Spring动态切换多数据源Demo

    此外,为了在代码中切换数据源,通常会有一个数据源路由的策略,例如在Service层根据业务逻辑决定使用哪个数据源。这可能涉及到AOP(面向切面编程)的使用,通过注解或配置来切换数据源。 在实际开发中,多数据源的...

    Spring+SpringMVC+Mybatis动态链接多数据源

    本项目“Spring+SpringMVC+Mybatis动态链接多数据源”旨在实现一个灵活、可扩展的数据源切换机制,以适应复杂的业务场景。 Spring框架作为Java领域中最广泛使用的轻量级框架,它提供了强大的依赖注入和AOP(面向切...

    spring多数据源

    通过扩展这个类或直接配置路由规则,我们可以实现数据源的动态选择。 3. **配置多数据源**:在Spring的XML配置文件中,我们需要定义多个DataSource bean,分别代表不同的数据库连接。这些数据源可以是Apache ...

    spring+mybatis 数据路由源代码

    本项目是基于Spring和Mybatis实现的数据路由功能,它允许应用程序在运行时动态地选择合适的数据源,实现了事务级别的控制,并且不需要依赖于特定的配置中心如Spring Cloud。 首先,我们要理解"多数据源"的概念。多...

    mybatis spring 多数据源

    标题 "mybatis spring 多数据源" 涉及到的...总的来说,"mybatis spring 多数据源"的主题涵盖了如何在Java应用中利用MyBatis和Spring进行多数据库管理,包括数据源配置、动态数据源路由、事务管理以及相关工具的使用。

    Springcloud 多数库 多数据源整合,查询动态切换数据库

    本主题聚焦于在Spring Cloud环境中实现多数据库和多数据源的整合,并且能够动态切换查询的数据库。这是一个复杂但至关重要的需求,特别是在大型企业级应用中,可能需要根据业务逻辑或用户权限连接到不同的数据库。 ...

    springboot3.2.3集成shardingsphere5.4.1及动态数据源demo项目

    这通常通过自定义数据源路由策略实现,例如基于业务标识、负载均衡等方式。在SpringBoot的配置类中,我们可以注册一个Bean,该Bean实现了DataSourceRouter接口,用于实现动态数据源的选择逻辑。 此外,...

    Spring多数据源分布式事务管理

    总的来说,Spring多数据源分布式事务管理是一项复杂的任务,涉及到Spring的AOP、数据源路由、事务管理等多个方面。通过Atomikos这样的JTA实现,我们可以有效地解决分布式环境下的事务一致性问题。同时,结合Druid和...

    SpringBoot+Atomikos+动态多数据源+事务+2种切换数据源的方式

    本主题将深入探讨如何利用SpringBoot结合Atomikos实现动态多数据源以及事务管理,并介绍两种切换数据源的方法。 首先,SpringBoot简化了传统Spring应用的初始化过程,它通过自动配置和starter包让开发者快速搭建...

    spring boot动态切换多数据源

    - `DynamicDataSourceRouter.java`:实现动态数据源路由,定义选择数据源的规则。 - `Service`和`Repository`层:在业务逻辑中使用动态数据源。 6. **核心代码解析** - `DataSourceConfig`:这里会创建多个`...

    spring多数据源的实现

    2. **配置数据源路由**:Spring的`AbstractRoutingDataSource`可以用来动态选择数据源。我们需要创建一个自定义的类继承`AbstractRoutingDataSource`,并覆盖`determineCurrentLookupKey()`方法来决定当前应该使用...

    spring boot数据源切换demo

    在Spring Boot应用中,数据源切换是一个常见的需求,特别是在分布式系统...在实际开发中,可以根据业务需求进行调整和优化,比如使用数据库路由策略自动选择数据源,或者利用Spring Cloud Data Flow进行数据源管理。

    spring boot多数据源自动路由

    通过分析这些文件,你可以深入了解如何在Spring Boot中设置和使用多数据源自动路由,包括数据源的配置、路由逻辑的实现、以及如何在代码中透明地使用这些数据源。这个项目是一个很好的学习资源,对于理解和实践...

    spring多数据源动态切换方案

    总结,Spring多数据源动态切换方案主要涉及创建多个数据源、使用AbstractRoutingDataSource进行动态路由、配置事务管理和在代码中切换数据源。通过这种方式,我们可以灵活地处理复杂的数据源切换场景,适应不同业务...

    mybatis-plus+动态数据源

    在IT行业中,数据库管理是核心任务之一,而动态数据源技术则是实现多数据库灵活切换的重要手段。本项目涉及的关键技术是"Mybatis-Plus"与"动态数据源"的结合使用,以及一系列相关的配置和扩展。下面将详细阐述这些...

Global site tag (gtag.js) - Google Analytics