mybatis 学习之多数据源整合

来源:互联网 发布:qinq端口 编辑:程序博客网 时间:2024/06/02 07:12
继续上篇文章如何使用mybatis3+spring3并且配置多数据源呢 

先上代码在讲解吧 
替换上一篇中spring中datasource的配置 
Java代码  收藏代码
  1. <!-- 数据源配置 -->  
  2. <bean id="ds1" class="org.apache.commons.dbcp.BasicDataSource"  
  3.     destroy-method="close">  
  4.     <property name="driverClassName" value="com.mysql.jdbc.Driver" />  
  5.     <property name="url"  
  6.         value="jdbc:mysql://localhost:3306/payoffdatabase?useUnicode=true&amp;characterEncoding=UTF-8" />  
  7.     <property name="username" value="root" />  
  8.     <property name="password" value="root" />  
  9.     <property name="defaultAutoCommit" value="true"></property>  
  10. </bean>  
  11.   
  12. <bean id="ds2" class="org.apache.commons.dbcp.BasicDataSource"  
  13.     destroy-method="close">  
  14.     <property name="driverClassName" value="com.mysql.jdbc.Driver" />  
  15.     <property name="url"  
  16.         value="jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=UTF-8" />  
  17.     <property name="username" value="root" />  
  18.     <property name="password" value="root" />  
  19.     <property name="defaultAutoCommit" value="true"></property>  
  20. </bean>  
  21.   
  22.   
  23.  <bean id="dataSource" class="a.b.router.DynamicDataSource">  
  24.     <property name="targetDataSources">  
  25.         <map key-type="java.lang.String">  
  26.             <entry value-ref="ds1" key="ds1"></entry>  
  27.             <entry value-ref="ds2" key="ds2"></entry>  
  28.         </map>  
  29.     </property>  
  30.     <property name="defaultTargetDataSource" ref="ds1"></property>  
  31. </bean>  


新的类DynamicDataSource 
Java代码  收藏代码
  1. package a.b.router;  
  2.   
  3. import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;  
  4.   
  5. public class DynamicDataSource extends AbstractRoutingDataSource {  
  6.     @Override  
  7.     protected Object determineCurrentLookupKey() {  
  8.         return DataSourceContextHolder.getDbType();  
  9.     }  
  10. }  

新的类DataSourceContextHolder 
Java代码  收藏代码
  1. package a.b.router;  
  2.   
  3. public class DataSourceContextHolder {  
  4.   
  5.     private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();  
  6.   
  7.     public static void setDbType(String dbType) {  
  8.         contextHolder.set(dbType);  
  9.     }  
  10.   
  11.     public static String getDbType() {  
  12.         return ((String) contextHolder.get());  
  13.     }  
  14.   
  15.     public static void clearDbType() {  
  16.         contextHolder.remove();  
  17.     }  
  18. }  


原来的单元测试新添加一行信息,修改为 
Java代码  收藏代码
  1. @Test  
  2. public void addTest() throws Exception {  
  3.     UserLogin userLogin = new UserLogin();  
  4.     userLogin.setPassword("102");  
  5.     userLogin.setUsername("102");  
  6.     DataSourceContextHolder.setDbType("ds2");  
  7.   
  8.     service.add(userLogin);  
  9. }  


最主要的变化是DynamicDataSource 类,这个类继承了AbstractRoutingDataSource,我们再继续考察,发现这个类实现了datasource这个接口。 

再仔细研究,发现我配置了多个数据源给DynamicDataSource,默认的数据源是ds1。 
我们研究下AbstractRoutingDataSource类的代码,主要是两个实现datasource的方法 
Java代码  收藏代码
  1. public Connection getConnection() throws SQLException {  
  2.     return determineTargetDataSource().getConnection();  
  3. }  
  4.   
  5. public Connection getConnection(String username, String password) throws SQLException {  
  6.     return determineTargetDataSource().getConnection(username, password);  
  7. }  

根据这段代码发现主要玄机都在determineTargetDataSource()方法上。 

Java代码  收藏代码
  1. protected DataSource determineTargetDataSource() {  
  2.         Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");  
  3.         Object lookupKey = determineCurrentLookupKey();  
  4.         DataSource dataSource = this.resolvedDataSources.get(lookupKey);  
  5.         if (dataSource == null && (this.lenientFallback || lookupKey == null)) {  
  6.             dataSource = this.resolvedDefaultDataSource;  
  7.         }  
  8.         if (dataSource == null) {  
  9.             throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");  
  10.         }  
  11.         return dataSource;  
  12.     }  

根据这段代码发现,首先在使用数据源之前,首先判断使用数据源的key,也就是我们配置给 
Java代码  收藏代码
  1. private Map<Object, Object> targetDataSources;  

这个map中的key值,找到key值之后再找到对应的datasource然后并使用这个数据源。 


从上面我们发现,实际上DynamicDataSource只是在内部封装了数据源,然后调用它,只不过在内部他加了一些控制而已。(此处不知道是否可以理解为代理模式) 

再深一步想想,此处使用的orm层是mybatis,如果换成hibernate呢,或者jdbctemplate呢。 
实际上这个方法都适用。
0 0