1.数据源配置:
jdbc_multiple.properties:
2.spring-mybatis.xml配置:
3.dbcontextholder类(作用是设置你当前的数据源)
4.使用方式:当你需要进行crud等数据库操作的之前 设置你需要使用的数据源即可
例:
其实再进行项目开发的时候,一个项目有可能不止用到一个数据源,为了提高数据库的水平伸缩性,需要对多个数据库实例进行管理,需要配置多数据源。
1. 配置多个数据源
这里以两个c3p0数据库连接池的数据源作为实例。在spring框架下使用c3p0的数据库需要加入c3p0-0.9.1.2.jar(现在最新的)这个支持包。这里以数据同步项目为例:
数据来源库的连接池数据源配置:
<bean id="datasourcefrom" class="com.mchange.v2.c3p0.combopooleddatasource">
<property name="driverclass" value="${jdbc.driver}" />
<property name="jdbcurl" value="${jdbc.from.url}" />
<property name="user" value="${jdbc.from.username}" />
<property name="password" value="${jdbc.from.password}" />
<property name="autocommitonclose" value="true" />
<property name="checkouttimeout" value="${cpool.checkouttimeout}" />
<property name="initialpoolsize" value="${cpool.minpoolsize}" />
<property name="minpoolsize" value="${cpool.minpoolsize}" />
<property name="maxpoolsize" value="${cpool.maxpoolsize}" />
<property name="maxidletime" value="${cpool.maxidletime}" />
<property name="acquireincrement" value="${cpool.acquireincrement}" />
<property name="maxidletimeexcessconnections" value="${cpool.maxidletimeexcessconnections}" />
</bean>
数据插入库的连接池数据源配置:
<bean id="datasourceto" class="com.mchange.v2.c3p0.combopooleddatasource">
<property name="jdbcurl" value="${jdbc.to.url}" />
<property name="user" value="${jdbc.to.username}" />
<property name="password" value="${jdbc.to.password}" />
注意:上面url,user,password等值是从classpath下的jdbc.properties中取得的。
通过spring获取属性文件中的值,以供配置文件使用:
<bean class="org.springframework.beans.factory.config.propertyplaceholderconfigurer">
<property name="locations" value="classpath:jdbc.properties" />
2. 扩展spring的abstractroutingdatasource抽象类,实现动态数据源。
abstractroutingdatasource中的抽象方法determinecurrentlookupkey是实现数据源的route的核心.这里对该方法进行override。
public class dynamicdatasource extends abstractroutingdatasource{
@override
protected object determinecurrentlookupkey() {
return dbcontextholder.getdbtype();
}
}
上下文dbcontextholder为一线程安全的threadlocal,具体代码如下:
public class dbcontextholder{
public static final string data_source_from = "datasourcefrom";
public static final string data_source_to = "datasourceto";
private static final threadlocal<string> contextholder = new threadlocal<string>();
public static void setdbtype(string dbtype) {
contextholder.set(dbtype);
public static string getdbtype() {
return contextholder.get();
public static void cleardbtype() {
contextholder.remove();
3.配置动态数据源
将dynamicdatasource bean加入到spring的上下文xml配置文件中去,同时配置dynamicdatasource的targetdatasources(多数据源目标)属性的map映射。
<bean id="dynamicdatasource" class="datasource.dynamicdatasource" >
<!-- 通过key-value的形式来关联数据源 -->
<property name="targetdatasources">
<map>
<entry value-ref="datasourcefrom" key="datasourcefrom"></entry>
<entry value-ref="datasourceto" key="datasourceto"></entry>
</map>
</property>
<property name="defaulttargetdatasource" ref="datasourcefrom" />
</bean>
4.使用动态数据源
例子中dynamicdatasource是继承与abstractroutingdatasource,而abstractroutingdatasource又是继承于org.springframework.jdbc.datasource.abstractdatasource,abstractdatasource实现了统一的datasource接口,所以dynamicdatasource同样可以当一个datasource使用。
在spring的jdbctemplate使用动态数据源的配置示例:
<!-- jdbctemplate使用动态数据源的配置 -->
<bean id="jdbctemplate" class="org.springframework.jdbc.core.jdbctemplate">
<property name="datasource">
<ref bean="dynamicdatasource" />
<!-- 对jdbctemplate的应用封装类 -->
<bean id="sqlbasedao" class="com.whty.dao.basedaoimpl">
<property name="jdbctemplate">
<ref bean="jdbctemplate" />
<bean id="sessionfactory" class="org.springframework.orm.hibernate3.annotation.annotationsessionfactorybean">
<!-- 和普通的datasource用法一样 -->
<property name="datasource" ref="dynamicdatasource" />
<property name="configlocations" value="classpath:hibernate.cfg.xml" />
<property name="hibernateproperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
5.事务管理
使用动态数据源的时候,可以看出和使用单数据源的时候相比,在使用配置上几乎没有差别,在进行性事务管理配置的时候也没有差别:
使用spring的jdbctemplate的事务管理配置示例:
<bean id="transactionmanager" class="org.springframework.jdbc.datasource.datasourcetransactionmanager">
<bean id="sqlbasedaoproxy" class="org.springframework.transaction.interceptor.transactionproxyfactorybean">
<property name="transactionmanager" ref="transactionmanager" />
<property name="target" ref="sqlbasedao" />
<property name="transactionattributes">
<prop key="insert*">propagation_required</prop>
<prop key="*">propagation_required,readonly</prop>
</props>
使用hibernate时的事务管理配置示例:
<tx:annotation-driven transaction-manager="transactionmanager"/>
<bean id="transactionmanager" class="org.springframework.orm.hibernate3.hibernatetransactionmanager">
<property name="sessionfactory" ref="sessionfactory" />
6.动态数据源的管理控制
如何选择控制每个业务中需要的具体数据源,可是使用手动控制:
applicationcontext context = new classpathxmlapplicationcontext("applicationcontext.xml");
basedao dao = (basedao) context.getbean("sqlbasedao", basedaoimpl.class);
try {
dbcontextholder.setcustomertype(dbcontextholder.data_source_from);
system.err.println(dao.select("select count(*) sum from test t ").get(0).get("sum"));
dbcontextholder.setcustomertype(dbcontextholder.data_source_to);
} catch (exception e) {
e.printstacktrace();
也可以采用aop的控制方式:
@aspect
public class dynamicdatasourceaspect {
@pointcut("execution (public service.impl..*.*(..))")
public void serviceexecution(){}
@before("serviceexecution()")
public void setdynamicdatasource(joinpoint jp) {
for(object o : jp.getargs()) {
//处理具体的逻辑 ,根据具体的境况customercontextholder.setcustomertype()选取datasource
}
7.总结
通过扩展spring的abstractroutingdatasource可以很好的实现多数据源的rout效果,而且对扩展更多的数据源有良好的伸缩性,只要增加数据源和修改dynamicdatasource的targetdatasources属性配置就好。在数据源选择控制上,可以采用手动控制(业务逻辑并不多的时候),也可以很好的用aop的@aspect在service的入口加入一个切面@pointcut,在@before里判断joinpoint的类容选定特定的数据源。