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

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.Driver
data01_jdbc_url=jdbc:mysql://172.16.14.40:3306/zhu?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull
data01_jdbc_username=zhu
data01_jdbc_password=zhu
jdbc_url=jdbc:mysql://172.16.14.52:3306/csca_manage?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull
jdbc_username=csca_manage
jdbc_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

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值