【增强】(非注解)SSM之配置多数据源

来源:互联网 发布:mac 系统优化 编辑:程序博客网 时间:2024/06/03 21:13

SSM单数据源的话,默认的数据源是DruidDataSource中指定数据源;

    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"        init-method="init" destroy-method="close">        <property name="driverClassName">            <value>${jdbc_driverClassName}</value>        </property>        <property name="url">            <value>${jdbc_url}</value>        </property>        <property name="username">            <value>${jdbc_username}</value>        </property>        <property name="password">            <value>${jdbc_password}</value>        </property>        <!-- 连接池最大使用连接数 -->        <property name="maxActive">            <value>20</value>        </property>        <!-- 初始化连接大小 -->        <property name="initialSize">            <value>1</value>        </property>        <!-- 获取连接最大等待时间 -->        <property name="maxWait">            <value>60000</value>        </property>        <!-- 连接池最大空闲 -->        <property name="maxIdle">            <value>20</value>        </property>        <!-- 连接池最小空闲 -->        <property name="minIdle">            <value>3</value>        </property>        <!-- 自动清除无用连接 -->        <property name="removeAbandoned">            <value>true</value>        </property>        <!-- 清除无用连接的等待时间 -->        <property name="removeAbandonedTimeout">            <value>180</value>        </property>        <!-- 连接属性 -->        <property name="connectionProperties">            <value>clientEncoding=UTF-8</value>        </property>    </bean>

正常来讲,一个DataSource对应的是一个sqlSessionFactory,如果配置多数据源的话,对应的是多个sqlSessionFactory,管理和配置起来都非常费劲,为什么不设置一个动态变换数据源的方法呢?
答案是肯定的,在spring4的源码中写到:

    /**     * Retrieve the current target DataSource. Determines the     * {@link #determineCurrentLookupKey() current lookup key}, performs     * a lookup in the {@link #setTargetDataSources targetDataSources} map,     * falls back to the specified     * {@link #setDefaultTargetDataSource default target DataSource} if necessary.     * @see #determineCurrentLookupKey()     * 检索当前目标数据源,通过determineCurrentLookupKey()方法确定当前的lookupkey,在数据源的map中执行一个lookup(通过setTargetDataSources()方法),如果没有的话回滚到默认的数据源。     */    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;    }    /**     * Determine the current lookup key. This will typically be     * implemented to check a thread-bound transaction context.     * <p>Allows for arbitrary keys. The returned key needs     * to match the stored lookup key type, as resolved by the     * {@link #resolveSpecifiedLookupKey} method.     * 确定当前的lookupkey。这通常是实现检查线程绑定的事务上下文,允许任意数量的key。返回的key需要匹配存储的key类型,通过resolveSpecifiedLookupKey()方法来解决。     */    protected abstract Object determineCurrentLookupKey();

然后进行xml配置:

jdbc.properties

jdbc_driverClassName=com.mysql.jdbc.Driverdata01_jdbc_url=jdbc:mysql://172.16.14.40:3306/zhu?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNulldata01_jdbc_username=zhudata01_jdbc_password=zhujdbc_url=jdbc:mysql://172.16.14.52:3306/csca_manage?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNulljdbc_username=csca_managejdbc_password=csca_manage

spring_mybatis.xml

...<bean id="dataSource01" class="com.alibaba.druid.pool.DruidDataSource"        init-method="init" destroy-method="close">        <property name="driverClassName">            <value>${jdbc_driverClassName}</value>        </property>        <property name="url">            <value>${data01_jdbc_url}</value>        </property>        <property name="username">            <value>${data01_jdbc_username}</value>        </property>        <property name="password">            <value>${data01_jdbc_password}</value>        </property>    </bean>    <!-- 配置datasource -->    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"        init-method="init" destroy-method="close">        <property name="driverClassName">            <value>${jdbc_driverClassName}</value>        </property>        <property name="url">            <value>${jdbc_url}</value>        </property>        <property name="username">            <value>${jdbc_username}</value>        </property>        <property name="password">            <value>${jdbc_password}</value>        </property>    </bean>    <bean id="dynamicDataSource" class="com.guide.datasource.DynamicDataSource">        <property name="targetDataSources">            <map key-type="java.lang.String">                <!-- 指定lookupKey和与之对应的数据源 -->                <entry key="dataSource01" value-ref="dataSource01"></entry>                <entry key="dataSource" value-ref="dataSource"></entry>            </map>        </property>        <!-- 这里可以指定默认的数据源 -->        <property name="defaultTargetDataSource" ref="dataSource" />    </bean>    <!-- 需要注意的是,此处的dynamicDataSource为数据源的动态替代品,其他事物和sqlSessionFactory等注入的数据源也得进行相应的替换。 -->...

DynamicDataSource.java

package com.guide.datasource;import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;public class DynamicDataSource extends AbstractRoutingDataSource {    @Override    protected Object determineCurrentLookupKey() {        // 从自定义的位置获取数据源标识        return DynamicDataSourceHolder.getDataSource();    }}

DynamicDataSourceHolder.java

package com.guide.datasource;public class DynamicDataSourceHolder {    /**     * 注意:数据源标识保存在线程变量中,避免多线程操作数据源时互相干扰     */    private static final ThreadLocal<String> THREAD_DATA_SOURCE = new ThreadLocal<String>();    public static String getDataSource() {        return THREAD_DATA_SOURCE.get();    }    public static void setDataSource(String dataSource) {        THREAD_DATA_SOURCE.set(dataSource);    }    public static void clearDataSource() {        THREAD_DATA_SOURCE.remove();    }}

使用的时候在实现类中:

public TUser query_ceshi() {    //切换数据源    DynamicDataSourceHolder.setDataSource(dataSource01);        return tUSerMapper.query_ceshi();    }

OK