spring+mybaties 配置多数据源
2016-02-25 17:47
441 查看
在实际的开发中遇到了需要2个数据源的情况。这里我们就需要配置多数据源了。
1 首先配置多数据源有2种实现方式
1)简单方式:一般情况下,我们可以配置多个数据源,然后为每个数据源写一套对应的sessionFactory和dao层代码我们称之为静态数据源配置
2)动态方式: 配置多个数据源,只对应一套sessionFactory,数据源之间可以动态切换。</span>
2 這两种方式相比较来看,第一种如果以后要配置多个数据源的话,对应都要配置sessionfactory. 第2种只需配置多个数据源自由切换对应一个sessionfactory 明显比第一个更装B一点。下面就是详细介绍我自己配置的第2中方法。首先是先配置2个数据源
<pre name="code" class="html"><beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd "> <description>公共的默认数据源配置</description> <!-- portal master数据库 --> <bean id="dataSource_master" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="${db.master.dbUrl}" /> <property name="username" value="${db.master.userName}" /> <property name="password" value="${db.master.passWord}" /> <!-- 连接池启动时创建的初始化连接数量(默认值为0) --> <property name="initialSize" value="1"/> <!-- 连接池中可同时连接的最大的连接数 默认 8--> <property name="maxActive" value="100"/> <!-- 连接池中最小的空闲的连接数,低于这个数量会被创建新的连接 --> <property name="minIdle" value="5"/> <!-- 连接池中最大的空闲的连接数,超过的空闲连接将被释放,如果设置为负数表示不限制 默认8 --> <property name="maxIdle" value="30"/> <!-- 最大等待时间,当没有可用连接时,连接池等待连接释放的最大时间,超过该时间限制会抛出异常,如果设置-1表示无限等待 --> <property name="maxWait" value="60000"/> <!-- 超过removeAbandonedTimeout时间后,是否进 行没用连接(废弃)的回收(默认为false,调整为true)--> <property name="removeAbandoned" value="true"/> <!-- 超过时间限制,回收没有用(废弃)的连接(默认为 300秒,调整为180) --> <property name="removeAbandonedTimeout" value="180"/> <!-- 默认提交 --> <property name="defaultAutoCommit" value="true"/> <!-- 打开检查,用异步线程evict进行检查 --> <property name="testWhileIdle" value="true"/> <!-- 就是在进行borrowObject进行处理时,对拿到的connection进行validateObject校验 --> <property name="testOnBorrow" value="false"/> <!-- 就是在进行returnObject对返回的connection进行validateObject校验,个人觉得对数据库连接池的管理意义不大 --> <property name="testOnReturn" value="false"/> <!-- 代表检查的sql --> <property name="validationQuery" value="select 1 from dual"/> <!-- 代表在执行检查时,通过statement设置,statement.setQueryTimeout(validationQueryTimeout) --> <property name="validationQueryTimeout" value="1"/> <property name="timeBetweenEvictionRunsMillis" value="30000"/> <!-- 代表每次检查链接的数量,建议设置和maxActive一样大,这样每次可以有效检查所有的链接. --> <property name="numTestsPerEvictionRun" value="100"/> </bean> <!-- portal master数据库 --> <bean id="dataSource_website" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="${db.website.dbUrl}" /> <property name="username" value="${db.website.userName}" /> <property name="password" value="${db.website.passWord}" /> <!-- 连接池启动时创建的初始化连接数量(默认值为0) --> <property name="initialSize" value="1"/> <!-- 连接池中可同时连接的最大的连接数 默认 8--> <property name="maxActive" value="100"/> <!-- 连接池中最小的空闲的连接数,低于这个数量会被创建新的连接 --> <property name="minIdle" value="5"/> <!-- 连接池中最大的空闲的连接数,超过的空闲连接将被释放,如果设置为负数表示不限制 默认8 --> <property name="maxIdle" value="30"/> <!-- 最大等待时间,当没有可用连接时,连接池等待连接释放的最大时间,超过该时间限制会抛出异常,如果设置-1表示无限等待 --> <property name="maxWait" value="60000"/> <!-- 超过removeAbandonedTimeout时间后,是否进 行没用连接(废弃)的回收(默认为false,调整为true)--> <property name="removeAbandoned" value="true"/> <!-- 超过时间限制,回收没有用(废弃)的连接(默认为 300秒,调整为180) --> <property name="removeAbandonedTimeout" value="180"/> <!-- 默认提交 --> <property name="defaultAutoCommit" value="true"/> <!-- 打开检查,用异步线程evict进行检查 --> <property name="testWhileIdle" value="true"/> <!-- 就是在进行borrowObject进行处理时,对拿到的connection进行validateObject校验 --> <property name="testOnBorrow" value="false"/> <!-- 就是在进行returnObject对返回的connection进行validateObject校验,个人觉得对数据库连接池的管理意义不大 --> <property name="testOnReturn" value="false"/> <!-- 代表检查的sql --> <property name="validationQuery" value="select 1 from dual"/> <!-- 代表在执行检查时,通过statement设置,statement.setQueryTimeout(validationQueryTimeout) --> <property name="validationQueryTimeout" value="1"/> <property name="timeBetweenEvictionRunsMillis" value="30000"/> <!-- 代表每次检查链接的数量,建议设置和maxActive一样大,这样每次可以有效检查所有的链接. --> <property name="numTestsPerEvictionRun" value="100"/> </bean>
4 然后是配置转换器
<bean id="data_dataSource" class="com.shangde.common.datesource.DynamicDataSource"> <property name="targetDataSources"> <map key-type="java.lang.String"> <entry key="dataSource_website" value-ref="dataSource_website" /> <entry key="dataSource_master" value-ref="dataSource_master" /> </map> </property> <property name="defaultTargetDataSource" ref="dataSource_master" /> </bean>
5配置切面
<!-- 动态数据源切换aop 先于事务的aop --> <bean id="dataSourceInterceptor" class="com.shangde.common.datesource.DataSourceInterceptor" /> <aop:config> <aop:aspect id="dataSourceAspect" ref="dataSourceInterceptor"> <aop:pointcut id="dsMaster" expression="execution(* com.shangde.master.mobile.*.service..*.*(..))" /> <aop:pointcut id="dsWebsite" expression="execution(* com.shangde.master.website.*.service..*.*(..))" /> <aop:before method="setdataSourceMaster" pointcut-ref="dsMaster"/> <aop:before method="setdataSourceWebsite" pointcut-ref="dsWebsite"/> </aop:aspect> </aop:config>6.配置sessionfactory
<bean id="sqlSessionFactory_master" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="data_dataSource" /> <!-- 全局sqlMapConfig.xml公共配置文件路径 --> <property name="configLocation" value="classpath:/mybatis_master.xml" /> <property name="typeAliasesPackage" value="com.shangde.master.dmo.*" /> </bean>
7 AbstractRoutingDataSource转换器代码
DynamicDataSource
package com.shangde.common.datesource; import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return CustomerContextHolder.getCustomerType(); } }
DataSourceInterceptor
package com.shangde.common.datesource; import org.aspectj.lang.JoinPoint; public class DataSourceInterceptor { public void setdataSourceMaster(JoinPoint jp) { CustomerContextHolder.setCustomerType("dataSource_master"); } public void setdataSourceWebsite(JoinPoint jp) { CustomerContextHolder.setCustomerType("dataSource_website"); } }
CustomerContextHolder
package com.shangde.common.datesource; public class CustomerContextHolder { public static final String DATA_SOURCE_MASTER = "dataSource_master"; public static final String DATA_SOURCE_WEBSITE = "dataSource_website"; private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>(); public static void setCustomerType(String customerType) { contextHolder.set(customerType); } public static String getCustomerType() { return contextHolder.get(); } public static void clearCustomerType() { contextHolder.remove(); } }
8 好了代码就这么多了 一些失误的配置自行解决。
原理: AbstractRoutingDataSource
能够通过key的值在 map中寻找对应的 值,也就是对应的数据源。然而怎么才能获得key的值呢?。我们对不同数据源分包(package)管理,同一包下的代码使用了同一数据源。通过AOP来实现,大家都知道web开发常见是三层结构:controller、service、dao。假设我们创建了2个包
package1 ,package2分别对应不同的数据源db1 和db2。在对应的包下面创建 我们 service 包 和 dao 包 ,我们只需要用AOP切
不同数据源下的包名的service的目录即可,当controller层调用service 类时,发现它在 package1 .service
包下,这是spring 切面就会调用 切面类,设置代表数据源的字符串db1然后AbstractRoutingDataSource根据db1這个key在map中找到对应的数据源 db1 .然后我们只是找到了這个数据源,那么怎么用呢。
我们发现AbstractRoutingDataSource
extends AbstractDataSource 发现他继承自 AbstractDataSource。而且刚才我们已经找到了我们到底要那个数据源,这样我们就可以直接使用
這个实现了 AbstractRoutingDataSource 的类作为数据源了。
相关文章推荐
- 【Stackoverflow好问题】Java += 操作符实质
- 设计模式:装饰器模式(为对象动态的添加功能)
- java 实体类转成json字符串
- Java垃圾回收工作原理
- 【JavaWeb Structs2学习】OGNL表达式
- eclipse断点调试
- AIX平台上使用JAVA程序连接到DB2数据库
- Spring-04-事务管理
- 初学Java的类加载与反射机制(一)
- java学习笔记-多态
- java实现给图片添加水印、透明度
- Stackoverflow JAVA TOP 100问题翻译征集令
- javaScritp 中prototype属性继承原理详解
- spring mvc集成shiro的web.xml配置详解
- Eclipse 中XML文件处理插件Rinzo
- Maven项目在eclipse中使用junit进行单元测试时报错:ClassNotFoundException
- java设计模式(二)---工厂方法模式
- RxJava 转换操作符 switchMap
- 使用myeclipse2014提交项目至git oschina
- Java中字符串倒序方法