隨筆-35  評(píng)論-33  文章-0  trackbacks-0
               本文的幾個(gè)關(guān)鍵詞,分布式數(shù)據(jù)源,數(shù)據(jù)源的動(dòng)態(tài)尋找,分布式事務(wù)JTA實(shí)現(xiàn)。
               對(duì)于一些較大規(guī)模的應(yīng)用,單個(gè)數(shù)據(jù)源是無法支撐起龐大的用戶量,需要引入多數(shù)據(jù)源,水平層面進(jìn)行分庫分表,降低單個(gè)DB的負(fù)載。接下來,我們程序里里面需 要管理不同數(shù)據(jù)源之前的程序調(diào)用,保證功能是WORK的。另外,跨庫就意味著之前單DB的事務(wù)就失效了,所以J2EE提出了JTA,分布式的事務(wù)管理,往 簡單了說,就是2步提交(two phase),比單步提交更苛刻。實(shí)際上他有兩個(gè)容器來管理,一個(gè)是資源管理器,一個(gè)是事務(wù)管理。小伙伴們可以發(fā)現(xiàn),這是一個(gè)環(huán)環(huán)相扣的過程。想解決一個(gè) 問題,你就得解決這幾個(gè)相關(guān)的問題。以下代碼,我也是參考了前輩們的思想,進(jìn)行了改造。

              第一步:XA數(shù)據(jù)源定義
               選定義一個(gè)抽象的父類源,這樣子類可以直接繼承
            
           1  <!-- 兩個(gè)數(shù)據(jù)源的功用配置,方便下面直接引用 -->
           2      <bean id="abstractXADataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init"
           3              destroy-method="close" abstract="true">
           4         <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"/>
           5         <property name="poolSize" value="10" />
           6         <property name="minPoolSize" value="10"/>
           7         <property name="maxPoolSize" value="30"/>
           8         <property name="borrowConnectionTimeout" value="60"/>
           9         <property name="reapTimeout" value="20"/>
          10         <!-- 最大空閑時(shí)間 -->
          11         <property name="maxIdleTime" value="60"/>
          12         <property name="maintenanceInterval" value="60" />
          13         <property name="loginTimeout" value="60"/>
          14         <property name="logWriter" value="60"/>
          15         <property name="testQuery">
          16             <value>select 1</value>
          17         </property>
          18         
          19     </bean>
          20 
             A源
               
           1 <!-- 配置第一個(gè)數(shù)據(jù)源 -->
           2     <bean id="dataSource_a" parent="abstractXADataSource">
           3     <!-- value只要兩個(gè)數(shù)據(jù)源不同就行,隨便取名 -->
           4         <property name="uniqueResourceName" value="mysql/sitestone" />
           5         <property name="xaDataSourceClassName"
           6             value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />
           7         <property name="xaProperties">
           8             <props>
           9                 <prop key="URL">${jdbc.url.spider}</prop>
          10                 <prop key="user">${jdbc.username}</prop>
          11                 <prop key="password">${jdbc.password}</prop>
          12             </props>
          13         </property>
          14     </bean>
             
          B   源

             
           1 <!-- 配置第二個(gè)數(shù)據(jù)源-->
           2     <bean id="dataSource_b" parent="abstractXADataSource">
           3 <!-- value只要兩個(gè)數(shù)據(jù)源不同就行,隨便取名 -->
           4         <property name="uniqueResourceName" value="mysql/sitesttwo" />
           5         <property name="xaDataSourceClassName"
           6             value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />
           7         <property name="xaProperties">
           8             <props>
           9                <prop key="URL">${jdbc_tb.url.spider}</prop>
          10                 <prop key="user">${jdbc_tb.username}</prop>
          11                 <prop key="password">${jdbc_tb.password}</prop>
          12             </props>
          13         </property>
          14     </bean>

          基于SPRING的AbstractRoutingDataSource動(dòng)態(tài)數(shù)據(jù)路由定義
          1   <bean name="dynamicDatasource" class="com.***.spring.datasource.CustomerDatasource">
          2         <property name="targetDataSources">
          3             <map>
          4                 <entry key="ds_1" value-ref="dataSource_a"/>
          5                 <entry key="ds_2" value-ref="dataSource_b"/>
          6             </map>
          7         </property>
          8         <property name="defaultTargetDataSource" ref="dataSource_a"    />
          9     </bean>
          我這里是使用MYBATIS來進(jìn)行ORM映射,配置如下
           1  <bean id="sqlSessionFactorya" class="org.mybatis.spring.SqlSessionFactoryBean">
           2         <property name="dataSource" ref="dataSource_a"/>
           3          <property name="typeAliasesPackage" value="com.****.spring.dschange.bean" />
           4          <!-- mapper和resultmap配置路徑 --> 
           5         <property name="mapperLocations">
           6             <list>
           7                 <!-- 表示在com.**目錄下的任意包下的resultmap包目錄中,以-resultmap.xml或-mapper.xml結(jié)尾所有文件 --> 
           8                 <value>classpath:com/***/spring/dschange/mapper/ShopMapper.xml</value>
           9             </list>
          10         </property>
          11     </bean>
          12     <bean id="sqlSessionFactoryb" class="org.mybatis.spring.SqlSessionFactoryBean">
          13         <property name="dataSource" ref="dataSource_b"/>
          14          <property name="typeAliasesPackage" value="com.****.spring.dschange.bean" />
          15           <!-- mapper和resultmap配置路徑 --> 
          16         <property name="mapperLocations">
          17             <list>
          18                 <!-- 表示在com.***目錄下的任意包下的resultmap包目錄中,以-resultmap.xml或-mapper.xml結(jié)尾所有文件 --> 
          19                 <value>classpath:com/***/spring/dschange/mapper/ShopMapper.xml</value>
          20             </list>
          21         </property>
          22     </bean>
          接下來,一個(gè)比較關(guān)鍵的地方是對(duì)MYBATIS的CustomSqlSessionTemplate的重寫,主要是引入動(dòng)態(tài)數(shù)據(jù)源sqlSessionFactory。針對(duì)不同的數(shù)據(jù)庫,調(diào)用其對(duì)應(yīng)的會(huì)話工廠,這對(duì)JTA是否啟用,比較重要。
           1  @Override
           2     public SqlSessionFactory getSqlSessionFactory() {
           3  
           4         SqlSessionFactory targetSqlSessionFactory = targetSqlSessionFactorys.get(DataSourceKeyHolder.getDataSourceKey());
           5         if (targetSqlSessionFactory != null) {
           6             return targetSqlSessionFactory;
           7         } else if (defaultTargetSqlSessionFactory != null) {
           8             return defaultTargetSqlSessionFactory;
           9         } else {
          10             Assert.notNull(targetSqlSessionFactorys, "Property 'targetSqlSessionFactorys' or 'defaultTargetSqlSessionFactory' are required");
          11             Assert.notNull(defaultTargetSqlSessionFactory, "Property 'defaultTargetSqlSessionFactory' or 'targetSqlSessionFactorys' are required");
          12         }
          13         return this.sqlSessionFactory;
          14     }
          XML配置
           1  <!-- 配置自定義的SqlSessionTemplate模板,注入相關(guān)配置 -->
           2     <bean id="sqlSessionTemplate" class="com.amos.spring.mybatis.CustomSqlSessionTemplate" scope="prototype">
           3         <constructor-arg ref="sqlSessionFactorya" />
           4         <property name="targetSqlSessionFactorys">
           5             <map>     
           6                 <entry value-ref="sqlSessionFactorya" key="ds_1"/>
           7                 <entry value-ref="sqlSessionFactoryb" key="ds_2"/>
           8             </map> 
           9         </property>
          10     </bean>

          掃描配置
          1  <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
           1     <!-- jta -->
           2     <bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
           3         init-method="init" destroy-method="close">
           4         <property name="forceShutdown">
           5             <value>true</value>
           6         </property>
           7     </bean>
           8  
           9     <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
          10         <property name="transactionTimeout" value="300" />
          11     </bean>
          12  
          13     <bean id="springTransactionManager"
          14         class="org.springframework.transaction.jta.JtaTransactionManager">
          15         <property name="transactionManager">
          16             <ref bean="atomikosTransactionManager" />
          17         </property>
          18         <property name="userTransaction">
          19             <ref bean="atomikosUserTransaction" />
          20         </property>
          21     </bean>
          22  <tx:annotation-driven transaction-manager="springTransactionManager" proxy-target-class="true" />
          2         <property name="basePackage" value="com.****.spring.dschange.mapper" />
          3         <property name="sqlSessionTemplateBeanName" value="sqlSessionTemplate"/>
          4         <property name="markerInterface" value="com.*****.spring.dschange.mapper.SqlMapper"/>
          5     </bean>

          最后就是JTA的實(shí)現(xiàn)配置
           1     <!-- jta -->
           2     <bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
           3         init-method="init" destroy-method="close">
           4         <property name="forceShutdown">
           5             <value>true</value>
           6         </property>
           7     </bean>
           8  
           9     <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
          10         <property name="transactionTimeout" value="300" />
          11     </bean>
          12  
          13     <bean id="springTransactionManager"
          14         class="org.springframework.transaction.jta.JtaTransactionManager">
          15         <property name="transactionManager">
          16             <ref bean="atomikosTransactionManager" />
          17         </property>
          18         <property name="userTransaction">
          19             <ref bean="atomikosUserTransaction" />
          20         </property>
          21     </bean>
          22  <tx:annotation-driven transaction-manager="springTransactionManager" proxy-target-class="true" />
          以上,XML配置相關(guān)的東西已經(jīng)完成。
          具體的代碼,請(qǐng)點(diǎn)擊GITHUB查看https://github.com/igool/spring-jta-mybatis


          我的微信公眾號(hào),歡迎溝通學(xué)習(xí)。
          posted on 2015-09-24 14:29 alexcai 閱讀(7106) 評(píng)論(0)  編輯  收藏

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 凉城县| 那坡县| 绵阳市| 阳谷县| 松原市| 昆山市| 阿坝县| 江孜县| 正镶白旗| 新干县| 东安县| 贵阳市| 宣威市| 民乐县| 二手房| 关岭| 天气| 曲松县| 得荣县| 常德市| 罗山县| 芜湖市| 古交市| 儋州市| 越西县| 乌拉特中旗| 布尔津县| 宝鸡市| 和林格尔县| 东乌珠穆沁旗| 卓资县| 垫江县| 海兴县| 南安市| 甘洛县| 蒲江县| 靖边县| 昌江| 伊吾县| 仪征市| 沛县|