Spring动态配置多数据源(转载)

Spring对于多数据源,以数据库表为参照,大体上可以分成两大类情况:

一是,表级上的跨数据库。即,对于不同的数据库却有相同的表(表名和表结构完全相同)。

二是,非表级上的跨数据库。即,多个数据源不存在相同的表。

Spring2.x的版本中采用Proxy模式,就是我们在方案中实现一个虚拟的数据源,并且用它来封装数据源选择逻辑,这样就可以有效地将数据源选择逻辑从Client中分离出来。Client提供选择所需的上下文(因为这是Client所知道的),由虚拟的DataSource根据Client提供的上下文来实现数据源的选择。

具体的实现就是,虚拟的DataSource仅需继承AbstractRoutingDataSource实现determineCurrentLookupKey()在其中封装数据源的选择逻辑。

1. 数据源的名称常量类:
package com.test;
public class DataSourceMap {
    public static final String TEST="test";
    public static final String LJH="ljh";
}

2. 建立一个获得和设置上下文环境的类,主要负责改变上下文数据源的名称

package com.test;
public class CustomerContextHolder {
    private static final ThreadLocal<String> customer = new ThreadLocal<String>();// 线程本地环境
    // 设置数据源类型 
    public static void setCustomerType(String customerType){
        customer.set(customerType);
    }
    // 获取数据源类型 
    public static String getCustomerType(){
        return customer.get();
    }
    // 清除数据源类型 
    public static void remove(){
        customer.remove();
    }
}

3. 建立动态数据源类,注意,这个类必须继承AbstractRoutingDataSource,且实现方determineCurrentLookupKey,该方法返回一个Object,一般是返回字符串

package com.test;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class DynamicDataSource extends AbstractRoutingDataSource{

    @Override
    protected Object determineCurrentLookupKey() {
        // 在进行DAO操作前,通过上下文环境变量,获得数据源的类型
        return CustomerContextHolder.getCustomerType();
    }
}

4. 编写spring的配置文件配置多个数据源

<?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-2.5.xsd">
    <!-- 数据源公共的内容 --> 
    <bean id="abstractDataSource"
        class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="user" value="root"></property>
        <property name="password" value="root"></property>
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
    </bean>
    <!-- 数据库ljh,继承abstractDataSource --> 
    <bean id="ljhDataSource" parent="abstractDataSource" >
        <property name="jdbcUrl"
            value="jdbc:mysql://localhost:3306/ljh">
        </property>
    </bean>
    <!-- 数据库test,继承abstractDataSource -->  
    <bean id="testDataSource" parent="abstractDataSource" >
        <property name="jdbcUrl"
            value="jdbc:mysql://localhost:3306/test">
        </property>
    </bean>
    <!-- 配置多数据源映射关系,动态数据源类,注意,这个类必须继承AbstractRoutingDataSource --> 
    <bean id="dataSource"    class="com.test.DynamicDataSource">
        <property name="targetDataSources">
            <map>
                <entry key="ljh" value-ref="ljhDataSource"></entry>
            </map>
        </property>
        <property name="defaultTargetDataSource" ref="testDataSource"></property>
    </bean> 
    <!-- sessionFactory的配置 --> 
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource">
            <ref bean="dataSource"/> 
        </property>
        <!-- 实体类资源映射 --> 
        <property name="mappingDirectoryLocations">
            <list>
                <value>classpath:com/test</value>
            </list>
        </property>
        <!-- 为sessionFactory 配置Hibernate属性 --> 
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
            </props>
        </property>
    </bean>
    <!-- 为dao配置sessionFactory --> 
    <bean id="userDaoImpl" class="com.test.UserDaoImpl">
        <property name="sessionFactory" ref="sessionFactory"></property>
    </bean>
    
</beans>

User类:

package com.test;
public class User {
    private Integer id;
    private String name;
    
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

user.hbm.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
    <class name="com.test.User" table="tuser">
        <id name="id">
            <generator class="native"></generator>
        </id>
        <property name="name" length="15"></property>
    </class>
</hibernate-mapping>

Dao类

package com.test;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public class UserDaoImpl extends HibernateDaoSupport{
    public void save(User user){
        this.getHibernateTemplate().save(user);
    }
}

测试类

package com.test;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        
        CustomerContextHolder.setCustomerType(DataSourceMap.TEST);
        UserDaoImpl userDaoImpl = (UserDaoImpl)ctx.getBean("userDaoImpl");
        User user = new User();
        user.setName("test");
        userDaoImpl.save(user);

        CustomerContextHolder.setCustomerType(DataSourceMap.LJH);
        user.setName("ljh");
        userDaoImpl.save(user);
        CustomerContextHolder.remove();
        
    }
}

相关推荐