spring动态设置多数据源

需求: 项目开发用的sping jdbctemplate, 之前数据源只有一个,现在数据源需要根据需求来进行变更, 也就是说

a用户------>需要访问A数据库服务器

b用户------>需要访问B数据库服务器

查询了资料,发现Spring提供了一个抽象类AbstractRoutingDataSource,为我们很方便的解决了这个问题。

实现:

Spring配置文件applicationContext.xml(包含相关bean类的代码)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jaxws="http://cxf.apache.org/jaxws"
    xmlns:jaxrs="http://cxf.apache.org/jaxrs"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://cxf.apache.org/jaxws
    http://cxf.apache.org/schemas/jaxws.xsd
    http://cxf.apache.org/jaxrs
    http://cxf.apache.org/schemas/jaxrs.xsd

    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd"><!--
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>

                 <value>/WEB-INF/jdbc_config.properties</value>
            </list>
        </property>
    </bean>
    -->

    <!--  这是原来的写法
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
      <property name="driverClassName" value="${jdbc.driverClassName}"/>
      <property name="url" value="${jdbc.url}"/>
      <property name="username" value="${jdbc.username}"/>
      <property name="password" value="${jdbc.password}"/>
    </bean>-->

    <bean id="serverA" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
      <property name="driverClassName"   value="com.mysql.jdbc.Driver"/>
      <property name="url"   value="jdbc:mysql://localhost:3306/test2?useUnicode=true&amp;characterEncoding=utf8" />
      <property name="username"  value="root"/>
      <property name="password"  value="tiger"/>
    </bean>

    <bean id="serverB" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
      <property name="driverClassName"   value="com.mysql.jdbc.Driver"/>
      <property name="url"   value="jdbc:mysql://112.112.11.132:3306/test?useUnicode=true&amp;characterEncoding=utf8"/>
      <property name="username"   value="root" />
      <property name="password"   value="tiger"/>
    </bean>

<!-- 这里是重点 -->
<bean id="dataSource" class="com.rr.datasource.DynamicDataSource">
    <property name="targetDataSources">
        <map key-type="java.lang.String">
            <entry key="server127" value-ref="serverA" />
            <entry key="server112" value-ref="serverB" />
        </map>
    </property>
    <property name="defaultTargetDataSource"  ref="serverA" />
</bean>

    <!--注入 spring jdbcTemplate -->
   <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
           <property name="dataSource" ref="dataSource"/>
   </bean>

    <!-- dao -->
    <bean id="initDaoImpl"  class="com.rr.dao.impl.InitDao">
        <property name="jdbcTemplate" ref="jdbcTemplate"></property>
    </bean>

    <!-- service -->
    <bean id="grantForCompany" class="com.rr.service.GrantForCompany">
        <property name="initDao" ref="initDaoImpl"></property>
        <property name="jdbcTemplate" ref="jdbcTemplate"></property>
    </bean>

    <!-- 事务管理 -->
   <bean id="transctionManager"
       class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <tx:annotation-driven transaction-manager="transctionManager"/>

 </beans>

2:  写一个DynamicDataSource类继承AbstractRoutingDataSource,并实现determineCurrentLookupKey方法

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

public class DynamicDataSource extends AbstractRoutingDataSource
{
    @Override
    protected Object determineCurrentLookupKey()
    {

        return DatabaseContextHolder.getCustomerType();
    }

}

3. 写一个线程安全的ThreadLocal(这个ThreadLocal详细见下篇博客,我之前也没有接触过)

public class DatabaseContextHolder
{
    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.当需要切换数据源时,调用一行代码就可以了(也可以用aop自动切换,根据自己需求吧)


DbContextHolder.setDbType("server112"); //server112 就是配置文件中那个targetDataSources的key

targetDataSources是一个map,可以看spring提供的源码.

 

 

参考博客:

 http://blog.sina.com.cn/s/blog_496782b1010100u1.html 详细讲解,大神的文章

http://blog.163.com/wang_hj138%40126/blog/static/140800106201263151242338/

时间: 2024-09-30 22:12:52

spring动态设置多数据源的相关文章

Spring动态配置多数据源

Spring动态配置多数据源,即在大型应用中对数据进行切分,并且采用多个数据库实例进行管理,这样可以有效提高系统的水平伸缩性.而这样的方案就会不同于常见的单一数据实例的方案,这就要程序在运行时根据当时的请求及系统状态来动态的决定将数据存储在哪个数据库实例中,以及从哪个数据库提取数据. 基本信息 1.Spring配置多数据源的方式和具体使用过程. 2.Spring对于多数据源,以数据库表为参照,大体上可以分成两大类情况: 一是,表级上的跨数据库.即,对于不同的数据库却有相同的表(表名和表结构完全相

Spring动态切换多数据源解决方案

spring动态配置多数据源,即在大型应用中对数据进行切分,并且采用多个数据库实例进行管理,这样可以有效提高系统的水平伸缩性.而这样的方案就会不同于常见的单一数据实例的方案,这就要程序在运行时根据当时的请求及系统状态来动态的决定将数据存储在哪个数据库实例中,以及从哪个数据库提取数据. Spring2.x以后的版本中采用Proxy模式,就是我们在方案中实现一个虚拟的数据源,并且用它来封装数据源选择逻辑,这样就可以有效地将数据源选择逻辑从Client中分离出来.Client提供选择所需的上下文(因为

Spring动态多数据源实例Demo

最近由于咨询Spring如何配置多数据源的人很多,一一回答又比较麻烦,而且以前的博文中的配置也是有问题,因此特此重新发布一个Demo给大家. Demo中共有两个数据源,即Mysql和Oracle,并已经进行简单测试,动态切换数据源是没有问题的,希望借此Demo能帮助到大家. Demo下载地址: Spring动态切换多数据源Demo:http://download.csdn.net/download/wangpeng047/8419953 另外我给些说明,阐述下多数据源配置时的重点: 1. 注意事

Spring AOP根据JdbcTemplate方法名动态设置数据源

说明:现在的场景是,采用数据库(Mysql)复制(binlog)的方式在两台不同服务器部署并配置主从(Master-Slave)关系: 并需要程序上的数据操作方法来访问不同的数据库,比如,update方法访问主数据库服务器,query方法访问从数据库服务器. 即把"增删改"和"查"分开访问两台服务器,当然两台服务器的数据库同步事先已经配置好. 然而程序是早已完成的使用Spring JdbcTemplate的架构,如何在不修改任何源代码的情况下达到<本文标题&g

Spring动态数据源实现读写分离

一.创建基于ThreadLocal的动态数据源容器,保证数据源的线程安全性 package com.bounter.mybatis.extension; /** * 基于ThreadLocal实现的动态数据源容器,保证DynamicDataSource的线程安全性 * @author simon * */ public class DynamicDataSourceHolder { private static final ThreadLocal<String> dataSourceHolde

dubbo服务+spring动态数据源出错

1:问题描述,以及分析 项目用了spring数据源动态切换,服务用的是dubbo.在运行一段时间后程序异常,更新操作没有切换到主库上. 这个问题在先调用读操作后再调用写操作会出现. 经日志分析原因: 第一:当程序运行一段时间后调用duboo服务时..([DubboServerHandler-192.168.1.106:20880-thread-199] [DubboServerHandler-192.168.1.106:20880-thread-200]) dubbo服务默认最大200线程(超过

基于Spring+Mybatis的多数据源动态切换

Spring单数据源直接在<bean id="dataSource">下配置数据源的各种连接参数.但动态数据源需要配置个各个数据源例如ds1.ds2等.然后在dataSource中动态根据传递过来的参数动态调用不同的数据源. 1.当进行访问时,首先通过DbContextHolder.setDbType("ds1");设置需要使用的数据源.DbContextHolder就是一个用来存储数据源信息的类,其中通过ThreadLocal来记录数据源信息. 2.D

spring框架中多数据源创建加载并且实现动态切换的配置实例代码

原文:spring框架中多数据源创建加载并且实现动态切换的配置实例代码 源代码下载地址:http://www.zuidaima.com/share/1774074130205696.htm 在我们的项目中遇到这样一个问题:我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库.我们以往在spring和hibernate框架中总是配置一个数据源,因而sessionFactory的dataSource属性总是指向这个数据源并且恒定不变,所有DAO在使用sessionFa

【sping揭秘】21、Spring动态数据源的切换

对于多个数据源的时候,我们如何切换不同的数据源进行数据库的操作呢? 当然我们可以直接定义2个DataSource,然后在每次获取connection的时候,从不同的DataSource中获取connection,类似如下 这种情况可以是2个数据库存放的数据性质是不同的,DataSource1存放1种数据,DataSource2存放另一种数据,每个数据库承担不同的数据访问请求,这2个是完全相互独立不相干的 这种就比较简单,那就是直接定义不同的jdbctemplate,设置不同的DataSource