转载自: http://elvis4139.iteye.com/blog/2278760
Spring单数据源直接在<bean id="dataSource">下配置数据源的各种连接参数。但动态数据源需要配置个各个数据源例如oracle、mysql等。然后在dataSource中动态根据传递过来的参数动态调用不同的数据源。
1、当进行访问时,首先通过DbContextHolder.setDbType("mysql");设置需要使用的数据源。DbContextHolder就是一个用来存储数据源信息的类,其中通过ThreadLocal来记录数据源信息。
2、DynamicDataSource类集成Spring的AbstractRoutingDataSource类,通过determineCurrentLookupKey方法来获取数据源类型,如果没有对应的数据源则使用defaultTargetDataSource配置。
注意:当设置了数据源之后会一直使用该数据源进行连接,除非使用 DbContextHolder.setDbType("oracle")重新设置数据源或使用DbContextHolder.clearDbType()清除,清除后使用defaultTargetDataSource属性指向的数据源进行连接。
properties
spring.datasource.oracle.driver-class-name=oracle.jdbc.OracleDriver spring.datasource.oracle.url= spring.datasource.oracle.username= spring.datasource.oracle.password= spring.datasource.mysql.driver-class-name=com.mysql.jdbc.Driver spring.datasource.mysql.url= spring.datasource.mysql.username= spring.datasource.mysql.password=
xml
<bean id="oracle" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close"> <property name="driverClassName" value="${spring.datasource.oracle.driver-class-name}" /> <property name="jdbcUrl" value="${spring.datasource.oracle.url}" /> <property name="username" value="${spring.datasource.oracle.username}" /> <property name="password" value="${spring.datasource.oracle.password}" /> </bean> <bean id="mysql" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close"> <property name="driverClassName" value="${spring.datasource.mysql.driver-class-name}" /> <property name="jdbcUrl" value="${spring.datasource.mysql.url}" /> <property name="username" value="${spring.datasource.mysql.username}" /> <property name="password" value="${spring.datasource.mysql.password}" /> </bean> <bean id="hikari" class="com.keen.coinpay.app.common.config.ds.DynamicDataSource"> <property name="targetDataSources"> <map key-type="java.lang.String"> <entry key="oracle" value-ref="oracle" /> <entry key="mysql" value-ref="mysql" /> </map> </property> <property name="defaultTargetDataSource" ref="oracle" /> </bean>
com.keen.coinpay.app.common.config.ds.DynamicDataSource
package com.keen.coinpay.app.common.config.ds; import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DbContextHolder.getDbType(); } }
com.keen.coinpay.app.common.config.ds.DbContextHolder
package com.keen.coinpay.app.common.config.ds; public class DbContextHolder { private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>(); public static void setDbType(String dbType) { contextHolder.set(dbType); } public static String getDbType() { String str = (String) contextHolder.get(); return str; } public static void clearDbType() { contextHolder.remove(); } }
测试
public ModelAndView list(HttpServletRequest request, HttpServletResponse response) throws Exception { DbContextHolder.setDbType("ds1"); List<DemoSysUser> list1 = demoSysUserService.getAll(); System.out.println(DbContextHolder.getDbType() + ".list.size()=" + list1.size()); DbContextHolder.setDbType("ds2"); List<DemoSysUser> list2 = demoSysUserService.getAll(); System.out.println(DbContextHolder.getDbType() + ".list.size()=" + list2.size()); DbContextHolder.clearDbType(); List<DemoSysUser> list = demoSysUserService.getAll(); ModelAndView mv = this.getAutoView().addObject("sysUserList", list); return mv; }
注意: 如果在配置了不同类型(MySQL/Oracle)动态数据源的情况下同时使用PageHelper做分页, 则需要给PageHelper配置参数[autoRuntimeDialect=true], 不然无法正确识别数据库Dialect, 进而无法按照正确的规则正确拼写分页SQL