spring + hibernate动态数据源配置

 在Spring 2.0.1中引入了AbstractRoutingDataSource, 该类充当了DataSource的路由中介, 能有在运行时, 根据某种key值来动态切换到真正的DataSource上, 同时对于不支持事务隔离级别的JTA事务来说, Spring还提供了另外一个类IsolationLevelDataSourceRouter来处理这个问题。

定义数据源类别:

[java] view plain copy print ?
  1. /** 
  2.  * com.ctc.common.DataSourceMap.java 
  3.  * 2011-11-15 
  4.  */  
  5. package com.ctc.common;  
  6.   
  7. /** 
  8.  * 数据源类别 
  9.  */  
  10. public class DataSourceMap {  
  11.   
  12.     /** 
  13.      * 主数据源 
  14.      */  
  15.     public static final String MASTER = "master";  
  16.       
  17.     /** 
  18.      * 从数据源 
  19.      */  
  20.     public static final String SLAVE = "slave";  
  21. }  
/**
 * com.ctc.common.DataSourceMap.java
 * 2011-11-15
 */
package com.ctc.common;

/**
 * 数据源类别
 */
public class DataSourceMap {

	/**
	 * 主数据源
	 */
	public static final String MASTER = "master";
	
	/**
	 * 从数据源
	 */
	public static final String SLAVE = "slave";
}

获取key值,从而动态切换数据源:

[java] view plain copy print ?
  1. /** 
  2.  * com.ctc.common.ContextHolder.java 
  3.  * 2011-11-15 
  4.  */  
  5. package com.ctc.common;  
  6.   
  7. /** 
  8.  * 用户当前上下文支持类 
  9.  * 主要负责设置上下文环境和获得上下文环境 
  10.  *  
  11.  */  
  12. public class ContextHolder {  
  13.   
  14.  private static final ThreadLocal contextHolder = new ThreadLocal();  
  15.   
  16.  public static void setCustomerType(String customerType) {  
  17.   contextHolder.set(customerType);  
  18.  }  
  19.   
  20.  public static String getCustomerType() {  
  21.   return (String) contextHolder.get();  
  22.  }  
  23.   
  24.  public static void clearCustomerType() {  
  25.   contextHolder.remove();  
  26.  }  
  27. }  
  28. /**
     * com.ctc.common.ContextHolder.java
     * 2011-11-15
     */
    package com.ctc.common;
    
    /**
     * 用户当前上下文支持类
    * 主要负责设置上下文环境和获得上下文环境 * */ public class ContextHolder { private static final ThreadLocal contextHolder = new ThreadLocal(); public static void setCustomerType(String customerType) { contextHolder.set(customerType); } public static String getCustomerType() { return (String) contextHolder.get(); } public static void clearCustomerType() { contextHolder.remove(); } }


    动态数据源的切换:

    [java] view plain copy print ?
    1. /** 
    2.  * com.ctc.common.DynamicDataSource.java 
    3.  * 2011-11-15 
    4.  */  
    5. package com.ctc.common;  
    6.   
    7. import org.apache.log4j.Logger;  
    8. import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;  
    9.   
    10. /** 
    11.  * 
    12.  */  
    13. public class DynamicDataSource extends AbstractRoutingDataSource {  
    14.    
    15.  private static final Logger logger = Logger.getLogger(DynamicDataSource.class);  
    16.   
    17.  /* (non-Javadoc) 
    18.   * @see org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource#determineCurrentLookupKey() 
    19.   */  
    20.  @Override  
    21.  protected Object determineCurrentLookupKey() {  
    22.   Object key = ContextHolder.getCustomerType();  
    23.   if(key != null){  
    24.    logger.debug("当前线程使用的数据源标识为 [ " +key.toString()+ " ].");  
    25.   }  
    26.   return key;  
    27.  }  
    28.   
    29. }  
    /**
     * com.ctc.common.DynamicDataSource.java
     * 2011-11-15
     */
    package com.ctc.common;
    
    import org.apache.log4j.Logger;
    import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
    
    /**
     *
     */
    public class DynamicDataSource extends AbstractRoutingDataSource {
     
     private static final Logger logger = Logger.getLogger(DynamicDataSource.class);
    
     /* (non-Javadoc)
      * @see org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource#determineCurrentLookupKey()
      */
     @Override
     protected Object determineCurrentLookupKey() {
      Object key = ContextHolder.getCustomerType();
      if(key != null){
       logger.debug("当前线程使用的数据源标识为 [ " +key.toString()+ " ].");
      }
      return key;
     }
    
    }
    
    


    spring配置文件中的配置:

    [html] view plain copy print ?
    1.   
    2.     <bean id="baseDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">  
    3.        <property name="driverClass" value="${jdbc.driver}" />  
    4.        <property name="initialPoolSize" value="${c3p0.initialPoolSize}" />  
    5.        <property name="minPoolSize" value="${c3p0.minPoolSize}" />  
    6.        <property name="maxPoolSize" value="${c3p0.maxPoolSize}" />  
    7.        <property name="maxIdleTime" value="${c3p0.maxIdleTime}" />  
    8.        <property name="acquireIncrement" value="${c3p0.acquireIncrement}" />  
    9.        <property name="idleConnectionTestPeriod" value="${c3p0.idleConnectionTestPeriod}" />  
    10.        <property name="automaticTestTable" value="${c3p0.automaticTestTable}" />  
    11.     bean>  
    12.   
    13.       
    14.     <bean id="masterDataSource" parent="baseDataSource">  
    15.        <property name="jdbcUrl" value="${jdbc.master.url}" />  
    16.        <property name="user" value="${jdbc.master.username}" />  
    17.        <property name="password" value="${jdbc.master.password}" />  
    18.          
    19.     bean>  
    20.       
    21.       
    22.     <bean id="slaveDataSource"  parent="baseDataSource">  
    23.        <property name="jdbcUrl" value="${jdbc.slave.url}" />  
    24.        <property name="user" value="${jdbc.slave.username}" />  
    25.        <property name="password" value="${jdbc.slave.password}" />  
    26.     bean>  
    27.       
    28.     <bean id="dataSource" class="com.ctc.common.DynamicDataSource">    
    29.        <property name="targetDataSources">    
    30.           <map key-type="java.lang.String">  
    31.             <entry key="master" value-ref="masterDataSource"/>  
    32.             <entry key="slave" value-ref="slaveDataSource"/>  
    33.           map>    
    34.        property>    
    35.        <property name="defaultTargetDataSource" ref="masterDataSource"/>    
    36.     bean>   
    
    	
           
           
           
           
           
           
           
           
        
    
    	
    	
           
           
           
           
        
        
        
    	
           
           
           
        
        
          
             
              
              	
    			
                
             
             
         


    把dataSource注入到SessionFactory中:

    [html] view plain copy print ?
    1.   
    2.    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">  
    3.       <property name="dataSource" ref="dataSource" />  
    4.       <property name="hibernateProperties">  
    5.           <props>  
    6.               <prop key="hibernate.jdbc.fetch_size">${hibernate.jdbc.fetch_size}prop>  
    7.              <prop key="hibernate.jdbc.batch_size">${hibernate.jdbc.batch_size}prop>  
    8.              <prop key="hibernate.dialect">${hibernate.dialect}prop>  
    9.              <prop key="hibernate.show_sql">falseprop>  
    10.              <prop key="hibernate.format_sql">trueprop>  
    11.              <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}prop>  
    12.              <prop key="hibernate.cache.use_second_level_cache">trueprop>  
    13.              <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProviderprop>  
    14.              <prop key="hibernate.cache.use_query_cache">trueprop>  
    15.              <prop key="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProviderprop>  
    16.           props>  
    17.       property>  
    18.     <property name="annotatedClasses">  
    19.         <list>  
    20.             <value>com.ctc.rbca.user.entity.Uservalue>  
    21.             <value>com.ctc.rbca.accessobject.entity.AccessObjectvalue>              
    22.         list>  
    23.     property>  
    24. bean>  
     
        
           
           
               
               	  ${hibernate.jdbc.fetch_size}
                  ${hibernate.jdbc.batch_size}
                  ${hibernate.dialect}
                  false
                  true
                  ${hibernate.hbm2ddl.auto}
                  true
                  org.hibernate.cache.EhCacheProvider
                  true
                  org.hibernate.connection.C3P0ConnectionProvider
               
           
    		
    			
    				com.ctc.rbca.user.entity.User
    				com.ctc.rbca.accessobject.entity.AccessObject			
    			
    		
    	


    在调用方法的前面加上ContextHolder.setCustomerType(DataSourceMap.SLAVE)就可以就可以动态切换了。

    你可能感兴趣的:(架构设计,多库)