首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

Spring动态数据源路由兑现

2012-08-25 
Spring动态数据源路由实现简单的翻译, 也算是一篇笔记.?原文:http://blog.springsource.com/2007/01/23/dy

Spring动态数据源路由实现

简单的翻译, 也算是一篇笔记.?
原文:http://blog.springsource.com/2007/01/23/dynamic-datasource-routing/?
在Spring 2.0.1中引入了AbstractRoutingDataSource, 该类充当了DataSource的路由中介, 能有在运行时, 根据某种key值来动态切换到真正的DataSource上, 同时对于不支持事务隔离级别的JTA事务来说, Spring还提供了另外一个类IsolationLevelDataSourceRouter来处理这个问题. 下面的例子将通过context来切换不同的数据源.?
首先定义一个Catalog的Dao:?
Java代码??Spring动态数据源路由兑现

  1. ?package?blog.datasource;??
  2. ??
  3. import?java.sql.ResultSet;??
  4. import?java.sql.SQLException;??
  5. import?java.util.List;??
  6. ??
  7. import?org.springframework.jdbc.core.simple.ParameterizedRowMapper;??
  8. import?org.springframework.jdbc.core.simple.SimpleJdbcDaoSupport;??
  9. ??
  10. public?class?Catalog?extends?SimpleJdbcDaoSupport?{??
  11. ??????????
  12. ???public?List<Item>?getItems()?{??
  13. ??????String?query?=?"select?name,?price?from?item";??
  14. ??????return?getSimpleJdbcTemplate().query(query,?new?ParameterizedRowMapper<Item>()?{??
  15. ????????????public?Item?mapRow(ResultSet?rs,?int?row)?throws?SQLException?{??
  16. ???????????????String?name?=?rs.getString(1);??
  17. ???????????????double?price?=?rs.getDouble(2);??
  18. ???????????????return?new?Item(name,?price);??
  19. ????????????}??
  20. ??????});??
  21. ???}??
  22. }??


然后定义一个Item的JavaBean?
Java代码??Spring动态数据源路由兑现
  1. package?blog.datasource;??
  2. ??
  3. public?class?Item?{??
  4. ??
  5. ???private?String?name;??
  6. ???private?double?price;??
  7. ??????????
  8. ???public?Item(String?name,?double?price)?{??
  9. ??????this.name?=?name;??
  10. ??????this.price?=?price;??
  11. ???}??
  12. ??
  13. ???public?String?getName()?{??
  14. ??????return?name;??
  15. ???}??
  16. ??
  17. ???public?double?getPrice()?{??
  18. ??????return?price;??
  19. ???}??
  20. ??
  21. ???public?String?toString()?{??
  22. ??????return?name?+?"?("?+?price?+?")";??
  23. ???}??
  24. ??
  25. }??


接着定义一个枚举类型, 用来表示不同的用户级别, 通过该类型将映射到不同的数据源?
Java代码??Spring动态数据源路由兑现
  1. public?enum?CustomerType?{??
  2. ???BRONZE,???
  3. ???SILVER,???
  4. ???GOLD??
  5. }??


下面是DataSource定义:?
Xml代码??Spring动态数据源路由兑现
  1. <bean?id="parentDataSource"??
  2. ?????????class="org.springframework.jdbc.datasource.DriverManagerDataSource"??
  3. ?????????abstract="true">??
  4. ???<property?name="driverClassName"?value="org.hsqldb.jdbcDriver"/>??
  5. ???<property?name="username"?value="sa"/>??
  6. </bean>??
  7. ??????????????????
  8. <bean?id="goldDataSource"?parent="parentDataSource">??
  9. ???<property?name="url"?value="jdbc:hsqldb:hsql://localhost:${db.port.gold}/blog"/>??
  10. </bean>??
  11. ??
  12. <bean?id="silverDataSource"?parent="parentDataSource">??
  13. ???<property?name="url"?value="jdbc:hsqldb:hsql://localhost:${db.port.silver}/blog"/>??
  14. </bean>??
  15. ??
  16. <bean?id="bronzeDataSource"?parent="parentDataSource">??
  17. ???<property?name="url"?value="jdbc:hsqldb:hsql://localhost:${db.port.bronze}/blog"/>??
  18. </bean>??
  19. ??
  20. <bean?class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">??
  21. ???<property?name="location"?value="classpath:/blog/datasource/db.properties"/>??
  22. </bean>??


AbstractRoutingDataSource 实现类?
Java代码??Spring动态数据源路由兑现
  1. package?blog.datasource;??
  2. ??
  3. import?org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;??
  4. ??
  5. public?class?CustomerRoutingDataSource?extends?AbstractRoutingDataSource?{??
  6. ??
  7. ???@Override??
  8. ???protected?Object?determineCurrentLookupKey()?{??
  9. ??????return?CustomerContextHolder.getCustomerType();??
  10. ???}??
  11. }??


CustomerContextHolder 是一个和LocalThread绑定的类, 定义如下:?
Java代码??Spring动态数据源路由兑现
  1. public?class?CustomerContextHolder?{??
  2. ??
  3. ???private?static?final?ThreadLocal<CustomerType>?contextHolder?=???
  4. ????????????new?ThreadLocal<CustomerType>();??
  5. ??????????
  6. ???public?static?void?setCustomerType(CustomerType?customerType)?{??
  7. ??????Assert.notNull(customerType,?"customerType?cannot?be?null");??
  8. ??????contextHolder.set(customerType);??
  9. ???}??
  10. ??
  11. ???public?static?CustomerType?getCustomerType()?{??
  12. ??????return?(CustomerType)?contextHolder.get();??
  13. ???}??
  14. ??
  15. ???public?static?void?clearCustomerType()?{??
  16. ??????contextHolder.remove();??
  17. ???}??
  18. }??


将dao bean和datasource bean结合起来, 至于dao和真正的datasource如何关联这个可以根据需要指定相关的策略和规则来实现:?
Xml代码??Spring动态数据源路由兑现
  1. <bean?id="catalog"?class="blog.datasource.Catalog">??
  2. ???<property?name="dataSource"?ref="dataSource"/>??
  3. </bean>??
  4. ??
  5. <bean?id="dataSource"?class="blog.datasource.CustomerRoutingDataSource">??
  6. ???<property?name="targetDataSources">??
  7. ??????<map?key-type="blog.datasource.CustomerType">??
  8. ?????????<entry?key="GOLD"?value-ref="goldDataSource"/>??
  9. ?????????<entry?key="SILVER"?value-ref="silverDataSource"/>??
  10. ??????</map>??
  11. ???</property>??
  12. ???<property?name="defaultTargetDataSource"?ref="bronzeDataSource"/>??
  13. </bean>??

下面通过一个TestCase来看看如何使用:?
Java代码??Spring动态数据源路由兑现
  1. public?class?CatalogTests?extends?AbstractDependencyInjectionSpringContextTests?{??
  2. ??
  3. ???private?Catalog?catalog;??
  4. ??
  5. ???public?void?setCatalog(Catalog?catalog)?{??
  6. ??????this.catalog?=?catalog;??
  7. ???}??
  8. ??
  9. ???public?void?testDataSourceRouting()?{??
  10. ??????CustomerContextHolder.setCustomerType(CustomerType.GOLD);??
  11. ??????List<Item>?goldItems?=?catalog.getItems();??
  12. ??????assertEquals(3,?goldItems.size());??
  13. ??????System.out.println("gold?items:?"?+?goldItems);??
  14. ??
  15. ??????CustomerContextHolder.setCustomerType(CustomerType.SILVER);??
  16. ??????List<Item>?silverItems?=?catalog.getItems();??
  17. ??????assertEquals(2,?silverItems.size());??
  18. ??????System.out.println("silver?items:?"?+?silverItems);??
  19. ??????????
  20. ??????CustomerContextHolder.clearCustomerType();??
  21. ??????List<Item>?bronzeItems?=?catalog.getItems();??
  22. ??????assertEquals(1,?bronzeItems.size());??
  23. ??????System.out.println("bronze?items:?"?+?bronzeItems);????????????????
  24. ???}??
  25. ??
  26. ???protected?String[]?getConfigLocations()?{??
  27. ??????return?new?String[]?{"/blog/datasource/beans.xml"};??
  28. ???}??????
  29. } ?

热点排行