Spring JDBC 多數據源管理

jopen 12年前發布 | 70K 次閱讀 Spring JEE框架

由于項目需要從已經運行的多個項目的數據庫中取值,所以就出現了需要訪問多個數據源的情況。

Spring配置文件

<!-- 屬性文件讀入 -->
    <bean id="propertyConfigurer"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath*:resources/spring/database.properties</value>
            </list>
        </property>
    </bean>

    <bean id="jdbcTemplate"
        class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
        <constructor-arg ref="dynamicDataSource" />
    </bean>

    <bean id="dynamicDataSource" class="com.primemis.datasource.DynamicDataSource">
        <!-- 通過key-value的形式來關聯數據源 -->
        <property name="targetDataSources">
            <map key-type="com.primemis.datasource.DatabaseType">
                <entry key="DEFAULT" value-ref="defaultDataSource"></entry>
                <entry key="COUNTER" value-ref="counterDataSource"></entry>
                <entry key="XPOS" value-ref="xposDataSource"></entry>
                <entry key="CONXPOS" value-ref="conxposDataSource"></entry>
                <entry key="ESPOS" value-ref="esposDataSource"></entry>
            </map>
        </property>
        <property name="defaultTargetDataSource" ref="defaultDataSource">
        </property>
    </bean>


    <!--MySql 數據源配置 Bgn -->
    <bean id="defaultDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
        destroy-method="close">
        <property name="driverClass" value="${mysql.driverclass}"></property>
        <property name="jdbcUrl" value="${mysql.jdbcurl}"></property>
        <property name="user" value="${mysql.user}"></property>
        <property name="password" value="${mysql.password}"></property>
        <property name="checkoutTimeout" value="${jdbc.checkoutTimeout}"></property>
        <property name="acquireIncrement" value="${jdbc.acquireIncrement}"></property>  <!-- 當連接池中的連接用完時,C3P0一次性創建新連接的數目2 -->
        <property name="initialPoolSize" value="${jdbc.initialPoolSize}"></property>  <!-- 初始化時創建的連接數,必須在minPoolSize和maxPoolSize之間 -->
        <property name="minPoolSize" value="${jdbc.minPoolSize}"></property>
        <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
        <!-- 最大空閑時間,超過空閑時間的連接將被丟棄 [需要注意:mysql默認的連接時長為8小時(28800)【可在my.ini中添加 wait_timeout=30(單位秒)設置連接超時】,這里設置c3p0的超時必須<28800] -->
        <property name="maxIdleTime" value="${jdbc.maxIdleTime}"></property>
        <!-- <property name="idleConnectionTestPeriod" value="60"></property> --> <!-- 每60秒檢查連接池中的空閑連接 -->
        <!-- <property name="maxStatements" value="20"></property> -->  <!-- jdbc的標準參數 用以控制數據源內加載的PreparedStatement數量,但由于預緩存的Statement屬 于單個Connection而不是整個連接 -->
    </bean>
    <!--MySql 數據源配置 End -->

    <!--客流系統 Sql Server 數據源配置 Bgn -->
    <bean id="counterDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
        destroy-method="close">
        <property name="driverClass" value="${counter.driverclass}"></property>
        <property name="jdbcUrl" value="${counter.jdbcurl}"></property>
        <property name="user" value="${counter.user}"></property>
        <property name="password" value="${counter.password}"></property>
        <property name="checkoutTimeout" value="${jdbc.checkoutTimeout}"></property>
        <property name="acquireIncrement" value="${jdbc.acquireIncrement}"></property>  <!-- 當連接池中的連接用完時,C3P0一次性創建新連接的數目2 -->
        <property name="initialPoolSize" value="${jdbc.initialPoolSize}"></property>  <!-- 初始化時創建的連接數,必須在minPoolSize和maxPoolSize之間 -->
        <property name="minPoolSize" value="${jdbc.minPoolSize}"></property>
        <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
        <!-- 最大空閑時間,超過空閑時間的連接將被丟棄 [需要注意:mysql默認的連接時長為8小時(28800)【可在my.ini中添加 wait_timeout=30(單位秒)設置連接超時】,這里設置c3p0的超時必須<28800] -->
        <property name="maxIdleTime" value="${jdbc.maxIdleTime}"></property>
        <!-- <property name="idleConnectionTestPeriod" value="60"></property> --> <!-- 每60秒檢查連接池中的空閑連接 -->
        <!-- <property name="maxStatements" value="20"></property> -->  <!-- jdbc的標準參數 用以控制數據源內加載的PreparedStatement數量,但由于預緩存的Statement屬 于單個Connection而不是整個連接 -->
    </bean>

    <!--客流系統 Sql Server 數據源配置 End -->

    <!-- Sybase JDBC信息配置 Bgn -->
    <bean id="aDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${Sybase.driverClassName}">
        </property>
        <property name="jdbcUrl" value="${a.url}"></property>
        <property name="user" value="${a.userName}"></property>
        <property name="password" value="${a.password}"></property>
    </bean>
    <bean id="bDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${Sybase.driverClassName}">
        </property>
        <property name="jdbcUrl" value="${b.url}"></property>
        <property name="user" value="${b.userName}"></property>
        <property name="password" value="${b.password}"></property>
    </bean>
    <bean id="cDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${Sybase.driverClassName}">
        </property>
        <property name="jdbcUrl" value="${c.url}"></property>
        <property name="user" value="${c.userName}"></property>
        <property name="password" value="${c.password}"></property>
    </bean>
    <!-- Sybase JDBC信息配置 End -->
DynamicDataSource類

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

public class DynamicDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        // TODO Auto-generated method stub
        return DatabaseContextHolder.getDatabaseType();
    }

}
DatabaseContextHolder類

import org.springframework.util.Assert;

public class DatabaseContextHolder {

    private static final ThreadLocal<DatabaseType> contextHolder = new ThreadLocal<DatabaseType>();

    public static void setDatabaseType(DatabaseType DatabaseType) {
        Assert.notNull(DatabaseType, "DatabaseType cannot be null");
        contextHolder.set(DatabaseType);
    }

    public static DatabaseType getDatabaseType() {
        return (DatabaseType) contextHolder.get();
    }

    public static void clearDatabaseType() {
        contextHolder.remove();
    }
}
Dao使用方式

@Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
    public int update(String sql, SqlParameterSource paramSource,
            DatabaseType type) {
        DatabaseContextHolder.setDatabaseType(type);
        int rows = this.jdbc.update(sql, paramSource);
        DatabaseContextHolder.clearDatabaseType();
        return rows;
    }

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!