zoukankan      html  css  js  c++  java
  • 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 感谢作者

  • 相关阅读:
    【BZOJ】1827: [Usaco2010 Mar]gather 奶牛大集会
    【BZOJ】1708: [Usaco2007 Oct]Money奶牛的硬币
    【BZOJ】1690: [Usaco2007 Dec]奶牛的旅行
    【BZOJ】1725: [Usaco2006 Nov]Corn Fields牧场的安排
    【BZOJ】1711: [Usaco2007 Open]Dining吃饭
    【BZOJ】1579: [Usaco2009 Feb]Revamping Trails 道路升级
    【BZOJ】1572: [Usaco2009 Open]工作安排Job
    【51NOD】1717 好数
    【POJ】3233 Matrix Power Series
    【BZOJ】1717: [Usaco2006 Dec]Milk Patterns 产奶的模式
  • 原文地址:https://www.cnblogs.com/panxuejun/p/6054857.html
Copyright © 2011-2022 走看看