mybatis怎樣配置數據庫集群


場景:一個讀數據源一個讀寫數據源。

 

原理:借助spring的【org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource】這個抽象類實現,看名字可以了解到是一個路由數據源的東西,這個類中有一個方法

我們是在DAO中指定數據庫,我們也可以根據需要在service或者controller中指定DB類型,需要記住的是setDbType是針對線程維度的。要考慮多線程的問題。

原理:借助spring的【org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource】這個抽象類實現,看名字可以了解到是一個路由數據源的東西,這個類中有一個方法

 

[java]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. /** 
  2.  * Determine the current lookup key. This will typically be 
  3.  * implemented to check a thread-bound transaction context. 
  4.  * <p>Allows for arbitrary keys. The returned key needs 
  5.  * to match the stored lookup key type, as resolved by the 
  6.  * {@link #resolveSpecifiedLookupKey} method. 
  7.  */  
  8. protected abstract Object determineCurrentLookupKey();  


每次去連數據庫的時候,spring會調用這個方法去找對應的數據源。返回值即對應的數據源的LookUpKey.那么這個LookUpKey在哪定義的呢?看下面的dataBase.xml的配置

 

 

[html]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. <!--數據源 讀寫 -->  
  2. <bean id="dataSourceRW" class="org.logicalcobwebs.proxool.ProxoolDataSource">  
  3.     <property name="alias" value="ihotelRW"></property>  
  4.     <property name="delegateProperties">  
  5.         <value>user=${jdbc.username},password=${jdbc.password}  
  6.         </value>  
  7.     </property>  
  8.     <property name="user" value="${jdbc.username}" />  
  9.     <property name="password" value="${jdbc.password}" />  
  10.     <property name="driver" value="${jdbc.driverClassName}" />  
  11.     <property name="driverUrl" value="${jdbc.url}" />  
  12.     <property name="maximumConnectionCount" value="${jdbc.maximumConnectionCount}"></property>  
  13.     <property name="maximumActiveTime" value="${jdbc.maximumActiveTime}"></property>  
  14.     <property name="maximumConnectionLifetime" value="${jdbc.maximumConnectionLifetime}"></property>  
  15.     <property name="prototypeCount" value="${jdbc.prototypeCount}"></property>  
  16.     <property name="houseKeepingSleepTime" value="${jdbc.houseKeepingSleepTime}"></property>  
  17.     <property name="simultaneousBuildThrottle" value="${jdbc.simultaneousBuildThrottle}"></property>  
  18.     <property name="houseKeepingTestSql" value="${jdbc.houseKeepingTestSql}"></property>  
  19.     <property name="verbose" value="${jdbc.verbose}"></property>  
  20.     <property name="statistics" value="${jdbc.statistics}"></property>  
  21.     <property name="statisticsLogLevel" value="${jdbc.statisticsLogLevel}"></property>  
  22. </bean>  
  23.   
  24.    <!--數據源 讀-->  
  25.    <bean id="dataSourceR" class="org.logicalcobwebs.proxool.ProxoolDataSource">  
  26.        <property name="alias" value="ihotelR"></property>  
  27.        <property name="delegateProperties">  
  28.            <value>user=${jdbc.r.username},password=${jdbc.r.password}  
  29.            </value>  
  30.        </property>  
  31.        <property name="user" value="${jdbc.r.username}" />  
  32.        <property name="password" value="${jdbc.r.password}" />  
  33.        <property name="driver" value="${jdbc.r.driverClassName}" />  
  34.        <property name="driverUrl" value="${jdbc.r.url}" />  
  35.        <property name="maximumConnectionCount" value="${jdbc.maximumConnectionCount}"></property>  
  36.        <property name="maximumActiveTime" value="${jdbc.maximumActiveTime}"></property>  
  37.        <property name="maximumConnectionLifetime" value="${jdbc.maximumConnectionLifetime}"></property>  
  38.        <property name="prototypeCount" value="${jdbc.prototypeCount}"></property>  
  39.        <property name="houseKeepingSleepTime" value="${jdbc.houseKeepingSleepTime}"></property>  
  40.        <property name="simultaneousBuildThrottle" value="${jdbc.simultaneousBuildThrottle}"></property>  
  41.        <property name="houseKeepingTestSql" value="${jdbc.houseKeepingTestSql}"></property>  
  42.        <property name="verbose" value="${jdbc.verbose}"></property>  
  43.        <property name="statistics" value="${jdbc.statistics}"></property>  
  44.        <property name="statisticsLogLevel" value="${jdbc.statisticsLogLevel}"></property>  
  45.    </bean>  
  46.      
  47.    <!-- 動態數據源 -->  
  48.    <bean id="dynamicDataSource" class="com.dao.datasource.DynamicDataSource">  
  49.        <!-- 通過key-value關聯數據源 -->  
  50.        <property name="targetDataSources">  
  51.            <map>  
  52.                <entry value-ref="dataSourceRW" key="dataSourceKeyRW"></entry>  
  53.                <entry value-ref="dataSourceR" key="dataSourceKeyR"></entry>  
  54.            </map>  
  55.        </property>  
  56.        <property name="defaultTargetDataSource" ref="dataSourceRW" />      
  57.    </bean>  
  58.   
  59. <!--mybatis與Spring整合 開始 -->  
  60. <bean id="sqlSessionFactory" name="sqlSessionFactory"  
  61.     class="org.mybatis.spring.SqlSessionFactoryBean">  
  62.     <property name="configLocation" value="classpath:conf/core/sqlMapConfig.xml" />  
  63.     <property name="dataSource" ref="dynamicDataSource" />  
  64. </bean>  

 

動態數據源dynamicDataSource中的dataSourceKeyRW、dataSourceKeyR就是

[java]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. protected abstract Object determineCurrentLookupKey();  

這個方法要返回的值。那么如何設置,讓這個方法的返回值是根據我們的需要返回dataSourceKeyRW、dataSourceKeyR呢?由於這個方法沒有入參,並且是spring自動調用的,因此考慮使用靜態變量存儲dataSource的key,在調用sql語句前設置靜態變量的值,然后在這個方法中得到靜態變量的值,返回。又考慮到多線程,同時可能會有很多請求,為避免線程之間相互干擾,考慮使用threadLocal。

 

先看存儲dataSourceKey的容器類。

 

[java]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. public class DBContextHolder {  
  2.   
  3.     /** 
  4.      * 線程threadlocal 
  5.      */  
  6.     private static ThreadLocal<String> contextHolder = new ThreadLocal<>();  
  7.   
  8.     private String DB_TYPE_RW = "dataSourceKeyRW";  
  9.     private String DB_TYPE_R = "dataSourceKeyR";  
  10.   
  11.     public String getDbType() {  
  12.         String db = contextHolder.get();  
  13.         if (db == null) {  
  14.             db = DB_TYPE_RW;// 默認是讀寫庫  
  15.         }  
  16.         return db;  
  17.     }  
  18.   
  19.     /** 
  20.      *  
  21.      * 設置本線程的dbtype 
  22.      *  
  23.      * @param str 
  24.      * @see [相關類/方法](可選) 
  25.      * @since [產品/模塊版本](可選) 
  26.      */  
  27.     public void setDbType(String str) {  
  28.         contextHolder.set(str);  
  29.     }  
  30.   
  31.     /** 
  32.      * clearDBType 
  33.      *  
  34.      * @Title: clearDBType 
  35.      * @Description: 清理連接類型 
  36.      */  
  37.     public static void clearDBType() {  
  38.         contextHolder.remove();  
  39.     }  
  40. }  


 

動態數據源的實現類。

 

 

[java]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. public class DynamicDataSource extends AbstractRoutingDataSource {  
  2.   
  3.     /* 
  4.      * (non-Javadoc) 
  5.      * @see javax.sql.CommonDataSource#getParentLogger() 
  6.      */  
  7.     @Override  
  8.     public Logger getParentLogger() throws SQLFeatureNotSupportedException {  
  9.         // TODO Auto-generated method stub  
  10.         return null;  
  11.     }  
  12.   
  13.     /** 
  14.      *  
  15.      * override determineCurrentLookupKey 
  16.      * <p> 
  17.      * Title: determineCurrentLookupKey 
  18.      * </p> 
  19.      * <p> 
  20.      * Description: 自動查找datasource 
  21.      * </p> 
  22.      *  
  23.      * @return 
  24.      */  
  25.     @Override  
  26.     protected Object determineCurrentLookupKey() {  
  27.         return DBContextHolder.getDbType();  
  28.     }  
  29.   
  30. }  


在DAO層中設置數據庫類型。

 

 

[java]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. /** 
  2.      * 添加郵件 
  3.      *  
  4.      * @param sms 
  5.      * @return 
  6.      */  
  7.     public boolean insertEmail(Email email) {  
  8.           
  9.         //根據具體需要設置不同的數據庫  
  10.         DBContextHolder.setDbType(DBContextHolder.DB_TYPE_RW);  
  11.         //DBContextHolder.setDbType(DBContextHolder.DB_TYPE_R);  
  12.         int result = this.getSqlSession().insert(STATEMENT + ".addEntity",  
  13.                 email);  
  14.         return result == 1;  
  15.     }  



 

 

 

在本例中,我們是在DAO中指定數據庫,我們也可以根據需要在service或者controller中指定DB類型,需要記住的是setDbType是針對線程維度的。要考慮多線程的問題。

 

本文轉自http://blog.csdn.net/xtj332/article/details/43953699 感謝作者


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM