創(chuàng)建基本的包 entity service dao 為了區(qū)分多數(shù)據(jù)源 一個(gè)用的是Mysql 一個(gè)是Oracle 方便測(cè)試,

創(chuàng)建MyBatis dao 映射 xml 文件

創(chuàng)建db.properties

我這里設(shè)置了2個(gè)數(shù)據(jù)源
創(chuàng)建Mybatis.xml 文件
建議創(chuàng)建2個(gè),也可以創(chuàng)建一個(gè).但是2個(gè) 耦合性降低
還需要用到工具類:
package com.cp.util.datasources;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
* 動(dòng)態(tài)切換數(shù)據(jù)庫(kù)
*
* @author Joey
* @project:SSM_MultiDataSource_CP
* @date:2017年4月27日
*
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDbType();
}
}
package com.cp.util.datasources;
/**
* 數(shù)據(jù)庫(kù)切換的工具類
*
* @author Joey
* @project:SSM_MultiDataSource_CP
* @date:2017年4月27日
*
*/
public class DataSourceContextHolder {
public static final String DATA_SOURCE_A = "dataSource1";
public static final String DATA_SOURCE_B = "dataSource2";
/** 數(shù)據(jù)源類型 */
private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
/**
* 設(shè)置數(shù)據(jù)源類型
*
* @param dbType
* 數(shù)據(jù)源類型
*/
public static void setDbType(String dbType) {
contextHolder.set(dbType);
}
/**
* 獲取數(shù)據(jù)源類型
*
* @return String
*/
public static String getDbType() {
return ((String) contextHolder.get());
}
/**
* 清除數(shù)據(jù)源類型
*/
public static void clearDbType() {
contextHolder.remove();
}
}
package com.cp.util.datasources;
import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
/**
* 數(shù)據(jù)源前置增強(qiáng)
*
* @author Joey
* @project:SSM_MultiDataSource_CP
* @date:2017年4月28日
*
*/
public class DataSourceAspect implements MethodBeforeAdvice,
AfterReturningAdvice {
@Override
public void afterReturning(Object returnValue, Method method,
Object[] args, Object target) throws Throwable {
DataSourceContextHolder.clearDbType();
}
@Override
public void before(Method method, Object[] args, Object target)
throws Throwable {
if (method.isAnnotationPresent(DataSource.class)) {
DataSource datasource = method.getAnnotation(DataSource.class);
DataSourceContextHolder.setDbType(datasource.value());
} else {
DataSourceContextHolder
.setDbType(DataSourceContextHolder.DATA_SOURCE_A);
}
}
}
package com.cp.util.datasources;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 動(dòng)態(tài)數(shù)據(jù)源(default:DataSourceContextHolder.DATA_SOURCE_A)
*
* @author Joey
* @project:SSM_MultiDataSource_CP
* @date:2017年4月28日
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface DataSource {
String value() default DataSourceContextHolder.DATA_SOURCE_A;
}
Spring配置文件 :

image.png
配置掃描包.
導(dǎo)入數(shù)據(jù)源連接信息
設(shè)置2個(gè)數(shù)據(jù)源

image.png
我使用的是Druid 個(gè)人覺得不錯(cuò)。推薦一下

image.png
Druid的日志記錄Filter

image.png
DynamicDataSource類是你剛剛自定義的工具類,上面有
導(dǎo)入2個(gè)數(shù)據(jù)源,默認(rèn)數(shù)據(jù)源是DataSource1

image.png
事物管理 和 開啟事物自動(dòng)掃描注解

image.png
加上前置增強(qiáng) DataSourceAspect類也是你剛剛自定義的工具類,上面有
最重要的一步: 開啟AOP注解支持

方法注解使用多數(shù)據(jù)源
在service里的方法要使用不同的數(shù)據(jù)源
方法直接注解:
@DataSource(DataSourceContextHolder.DATA_SOURCE_B)
默認(rèn)的使用是A 可以自己配置
注意: DataSourceContextHolder類里的DATA_SOURCE_A 和 DATA_SOURCE_B 的值要和spring配置文件對(duì)應(yīng)

image.png