SpringMVC+Mybatis 如何配置多个数据源并切换?
最近公司一个项目需要连接两个数据库(a和b)操作,有的模块查询a库,有的模块查询b库,因此需要改造下,项目后台用的是springmvc+mybatis+mysql架构,折腾了两天后终于搞定了,在这里记录过改造过程。
使用场景
多数据源的使用的场景一般有:
- 主从数据库切换
- 读写分离
- 兼容旧库
实现原理
spring2.x的版本中采用proxy模式,就是在方案中实现一个虚拟的数据源,并且用它来封装数据源选择逻辑,这样就可以有效地将数据源选择逻辑从client中分离出来。client提供选择所需的上下文,由虚拟的dynamicdatasource根据client提供的上下文来实现数据源的选择。
具体的实现是虚拟的dynamicdatasource仅需继承abstractroutingdatasource实现determinecurrentlookupkey(),该方法返回需要使用的datasource的key值,然后根据这个key从resolveddatasources这个map里取出对应的datasource,如果找不到则用默认的resolveddefaultdatasource。
详细实现过程
- 修改spring的配置文件
配置文件里需要配置多个数据源,改造后主要配置如下:
<bean id="datasourcetargeta" class="com.mchange.v2.c3p0.combopooleddatasource" destroy-method="close" scope="singleton"> <property name="driverclass" value="${jdbc.a.driverclassname}" /> <property name="jdbcurl" value="${jdbc.a.url}" /> <property name="user" value="${jdbc.a.username}" /> <property name="password" value="${jdbc.a.password}" /> <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。default: 3 --> <property name="acquireincrement" value="${c3p0.acquireincrement}"></property> <!--初始化时获取三个连接,取值应在minpoolsize与maxpoolsize之间。default: 3 --> <property name="initialpoolsize" value="${c3p0.initialpoolsize}"></property> <!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。default: 0 --> <property name="maxidletime" value="${c3p0.maxidletime}"></property> <!--连接池中保留的最大连接数。default: 15 --> <property name="maxpoolsize" value="${c3p0.maxpoolsize}"></property> <property name="minpoolsize" value="${c3p0.minpoolsize}"></property> <!--两次连接中间隔时间,单位毫秒。default: 1000 --> <property name="acquireretrydelay" value="1000"></property> <!--定义在从数据库获取新连接失败后重复尝试的次数。default: 30 --> <property name="acquireretryattempts" value="60"></property> <!--获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效保留,并在下次调用getconnection()的时候继续尝试获取连接。如果设为true,那么在尝试获取连接失败后该数据源将申明已断开并永久关闭。default: false --> <property name="breakafteracquirefailure" value="false"></property> </bean> <bean id="datasourcetargetb" class="com.mchange.v2.c3p0.combopooleddatasource" destroy-method="close" scope="singleton"> <property name="driverclass" value="${jdbc.b.driverclassname}" /> <property name="jdbcurl" value="${jdbc.b.url}" /> <property name="user" value="${jdbc.b.username}" /> <property name="password" value="${jdbc.b.password}" /> <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。default: 3 --> <property name="acquireincrement" value="${c3p0.acquireincrement}"></property> <!--初始化时获取三个连接,取值应在minpoolsize与maxpoolsize之间。default: 3 --> <property name="initialpoolsize" value="${c3p0.initialpoolsize}"></property> <!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。default: 0 --> <property name="maxidletime" value="${c3p0.maxidletime}"></property> <!--连接池中保留的最大连接数。default: 15 --> <property name="maxpoolsize" value="${c3p0.maxpoolsize}"></property> <property name="minpoolsize" value="${c3p0.minpoolsize}"></property> <!--两次连接中间隔时间,单位毫秒。default: 1000 --> <property name="acquireretrydelay" value="1000"></property> <!--定义在从数据库获取新连接失败后重复尝试的次数。default: 30 --> <property name="acquireretryattempts" value="60"></property> <!--获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效保留,并在下次调用getconnection()的时候继续尝试获取连接。如果设为true,那么在尝试获取连接失败后该数据源将申明已断开并永久关闭。default: false --> <property name="breakafteracquirefailure" value="false"></property> </bean> <!-- 动态数据源 --> <bean id="dynamicdatasource" class="com.test.util.dynamicdatasource" > <property name="targetdatasources"> <map key-type="java.lang.string"> <entry value-ref="datasourcetargeta" key="datasourcetargeta"></entry> <entry value-ref="datasourcetargetb" key="datasourcetargetb"></entry> </map> </property> <property name="defaulttargetdatasource" ref="datasourcetargeta" > </property> </bean> <bean id="txmanager" class="org.springframework.jdbc.datasource.datasourcetransactionmanager"> <property name="datasource" ref="dynamicdatasource" /> </bean> <!-- mybatis orm operation class --> <bean id="sqlsessionfactory" class="org.mybatis.spring.sqlsessionfactorybean"> <property name="datasource" ref="dynamicdatasource" /> <property name="mapperlocations"> <list> <value>classpath*:com/test/**/*mapper.xml</value> </list> </property> <property name="configlocation" value="classpath:provider-sql-map-config.xml" /> </bean>
- 添加动态数据源管理类
dynamicdatasource类继承abstractroutingdatasource,实现determinecurrentlookupkey()方法。
package com.test.util; import com.test.util.customercontextholder; import org.springframework.jdbc.datasource.lookup.abstractroutingdatasource; /** * 动态数据源管理类 * */ public class dynamicdatasource extends abstractroutingdatasource { @override protected object determinecurrentlookupkey() { return customercontextholder.getcustomertype(); } }
- 数据源切换类
customercontextholder类可以实现数据源a和b的切换,数据源标识保存在线程变量中,避免多线程操作数据源时互相干扰
package com.test.util; /** * 数据源切换类 * */ public class customercontextholder { public static final string data_source_default = "datasourcetargeta"; public static final string data_source_b = "datasourcetargetb"; 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(); } }
- 使用多数据源代码
下面是controller层代码,需要查询b数据源,查询完成后切换为默认数据源a,具体代码如下:
/** * 订单列表查询,查询b数据源 * * @param request * @return */ @requestmapping(value = "/list") public string list(httpservletrequest request, integer cid) { //设置数据源b customercontextholder.setcustomertype(customercontextholder.data_source_b); list<order> orderlist = salarybillservice.getsalaryorderbyorgid(cid); request.setattribute("orderlist", orderlist); //切换回默认数据源a customercontextholder.setcustomertype(customercontextholder.data_source_default); return "/jsp/order"; }
上述四步操作完成后即可实现springmvc+mybatis配置多个数据源并切换,有问题欢迎留言沟通哦!
推荐阅读
1.一分钟带你学会利用mybatis-generator自动生成代码!
3.springboot系列-整合mybatis(注解方式)
4.springboot系列-整合mybatis(xml配置方式)
限时领取免费java相关资料,涵盖了java、redis、mongodb、mysql、zookeeper、spring cloud、dubbo/kafka、hadoop、hbase、flink等高并发分布式、大数据、机器学习等技术。
关注下方公众号即可免费领取:
本文由博客一文多发平台 openwrite 发布!
推荐阅读
-
Spring boot如何快速的配置多个Redis数据源
-
SpringBoot Mybatis如何配置多数据源并分包
-
mybatis如何配置使用多个数据源(environment)?
-
SpringMVC+Mybatis 如何配置多个数据源并切换?
-
Spring boot如何快速的配置多个Redis数据源
-
SpringBoot Mybatis如何配置多数据源并分包
-
Magento中如何在模块中使用多张数据表并配置多个model?
-
mybatis如何配置使用多个数据源(environment)?
-
mybatis如何配置使用多个数据源(environment)?
-
SpringMVC+Mybatis 如何配置多个数据源并切换?