spring dataSourceRouterが自動的にデータソースを切り替えます.

20612 ワード

spring多データソースの切り替えは主にAbstractRoutingDataSourceというルート類を使用しています.私達がカスタマイズしたルート配布類がAbstractRoutingDataSource類を継承した後、determinerentLook ukey()を書き直します.書き換えの内容は私達の配布規則です.この方法はspringがデータソースを選択する必要がある時に実行されます.その後、私達のカスタムルールに従って自動的に配信され、多データソースの切り替えが可能になります.
ステップは以下の通りです.
1、複数のデータソースを設定する
 <!-- 
  <bean id="c3p0DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="${jdbc.driverClass}" />
    <property name="jdbcUrl" value="${jdbc.jdbcUrl}" />
    <property name="user" value="${jdbc.user}" />
    <property name="password" value="${jdbc.password}" />
    <property name="initialPoolSize" value="${c3p0.initialPoolSize}" />
    <property name="minPoolSize" value="${c3p0.minPoolSize}" />
    <property name="maxPoolSize" value="${c3p0.maxPoolSize}" />
    <property name="maxStatements" value="${c3p0.maxStatements}" />
    <property name="checkoutTimeout" value="${c3p0.checkoutTimeout}" />
    <property name="maxIdleTime" value="${c3p0.maxIdleTime}" />
    <property name="idleConnectionTestPeriod" value="${c3p0.idleConnectionTestPeriod}" />
  </bean>
 -->

  <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="url" value="${jdbc.jdbcUrl}" /> <property name="username" value="${jdbc.user}" /> <property name="password" value="${jdbc.password}" /> <property name="initialSize" value="${druid.initialSize}" /> <property name="minIdle" value="${druid.minIdle}" /> <property name="maxActive" value="${druid.maxActive}" /> <property name="maxWait" value="${druid.maxWait}" /> <property name="timeBetweenEvictionRunsMillis" value="${druid.timeBetweenEvictionRunsMillis}" /> <property name="minEvictableIdleTimeMillis" value="${druid.minEvictableIdleTimeMillis}" /> <property name="validationQuery" value="${druid.validationQuery}" /> <property name="testWhileIdle" value="${druid.testWhileIdle}" /> <property name="testOnBorrow" value="${druid.testOnBorrow}" /> <property name="testOnReturn" value="${druid.testOnReturn}" /> <property name="poolPreparedStatements" value="${druid.poolPreparedStatements}" /> <property name="maxPoolPreparedStatementPerConnectionSize" value="${druid.maxPoolPreparedStatementPerConnectionSize}" /> <property name="filters" value="${druid.filters}" /> </bean>
<bean id="druidDataSource_1" parent="druidDataSource"> <property name="url" value="${jdbc.jdbcUrl1}" /> </bean>
2、ルータを配置して、このoddとevenに注意してください.彼は私達のデータソースの標識です.AbstractRoutingDataSourceルートdetermine Curent Lookukey()この方法の中でどれを返しますか?それに対応するデータソースです.「odd」を返すなら、druidDataSourceデータソースです.
<bean id="dataSourcreRouter" class="cn.yyh.router.NMRoutingDataSource">

      <property name="targetDataSources">

            <map>

                <entry key="odd" value-ref="druidDataSource" />

                <entry key="even" value-ref="druidDataSource_1" />

            </map>

      </property>

      <property name="defaultTargetDataSource" ref="druidDataSource" />

</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSourcreRouter" /> </bean>
3、AbstractRoutingDataSourceルートの配布器を編纂して、このNMRoutingTokenは何のラクトですか?このNMRoutingTokenは、ThreadLocalに記憶されているトークンの一つです.ThreadLocalは、現在のスレッド内のmapオブジェクトです.
public class NMRoutingDataSource extends AbstractRoutingDataSource {



    protected Object determineCurrentLookupKey() {

         NMRoutingToken token = NMRoutingToken.getCurrentToken();

        if (token != null) {

            String dataSourceName = token.getDataSourceName();

            //     

            NMRoutingToken.unbindToken();

            return dataSourceName;

        }

        return null;

    }



}
4、見えますが、実はNMRoutingTokenは現在のスレッドの中にあるThreadLocalに文字列を格納しています.前にdetermine Currennt Lookukeyと言いました.何に戻りますか?springは自動的にそのデータソースを選択します.それなら、私達new NMRoutingToken(「odd」)は彼をThreadLocalに結びつけて、determine Current Lookukey()で取り出せばいいです.
public class NMRoutingToken {



    private static ThreadLocal<NMRoutingToken> token = new ThreadLocal<NMRoutingToken>();

    private String dataSourceName;

    

    public String getDataSourceName() {

        return dataSourceName;

    }



    public NMRoutingToken(String dataSourceName) {

        super();

        this.dataSourceName = dataSourceName;

        bindToken(this);

    }



    /**

     *            

     */

    private static void bindToken(NMRoutingToken t) {

        token.set(t);

    }



    /**

     *             

     */

    public static void unbindToken() {

        token.remove();

    }



    /**

     *             

     */

    public static NMRoutingToken getCurrentToken() {

        return token.get();

    }



}
5、テスト
public class NMDataSourceTest extends BaseTest {

    @Autowired

    private UserMapper userMapper;

    @Autowired

    private IUserService userService;



    @Test

    /**

     *      

     */

    public void testMapper() {

        /**

         *         ,       

         */

        int count1 = userMapper.getCount();

        System.out.println(count1);



        /**

         *        odd

         */

        NMRoutingToken token = new NMRoutingToken("odd");

        count1 = userMapper.getCount();

        System.out.println(count1);



        /**

         *        even

         */

        token = new NMRoutingToken("even");

        count1 = userMapper.getCount();

        System.out.println(count1);



        /**

         *           

         */

        token = new NMRoutingToken("asdf");

        count1 = userMapper.getCount();

        System.out.println(count1);

    }



    @Test

    /**

     *     

     *   ,  tomcat         ,        ,         ,

     *         ,       NMRoutingDataSource determineCurrentLookupKey()   ,

     *              ,             

     */

    public void testService() {

        userService.getNMCount();

    }

}
@Transactional(readOnly = true)

    public void getNMCount() {

        int count1 = -1;

        /**

         *      even

         */

        new NMRoutingToken("even");

        count1 = userMapper.getCount();

        System.out.println(count1);

        

        /**

         *      odd  ,      even   

         */

        new NMRoutingToken("odd");

        count1 = userMapper.getCount();

        System.out.println(count1);

    }
実例ダウンロード:サンプルのダウンロード
ここでトークンに格納されている文字列は、最も簡単な配布規則であり、対象の属性に応じて自動的に選択する必要がある場合は、トークンに対応するオブジェクトを記憶して、経路の中でIDなどの属性を取り出し、その後、私たちのルールに従って動的に戻ります.これは私達が自分で指定する必要がありません.
  :tomcat          ,        service      。

           service          。

 :

@Tranctional

AService(){

    methodA(){

        dataSourceA.insert();

        dataSourceB.update();

    }

}

AService(){

    @Tranctional

    methodA(){

        dataSourceA.insert();

        dataSourceB.update();

    }

}

    (          ,         )      ,    src/test/java/ResourceTest.java





          :

Service(){

    aService.insert();

    bService.update();

}

AService{

    @Tranctional

    insert();

}

BService{

    @Tranctional

    update();

}