在開發中因需求在項目中需要實現多數據源(雖然項目框架是SpringCloud,但是因其中只是單獨的查詢操作,覺得沒必要開發一個項目,所以采用多數據源來進行實現)
1.在配置文件中創建多個數據連接配置
spring.datasource.primary.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.primary.url=jdbc:mysql://127.0.0.1:3306/test1?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&useSSL=false&autoReconnect=true&failOverReadOnly=false spring.datasource.primary.username=root spring.datasource.primary.password=root spring.datasource.primary.driverClassName = com.mysql.jdbc.Driver spring.datasource.primary.max-wait=10000 spring.datasource.primary.max-idle=8 spring.datasource.primary.min-idle=8 spring.datasource.primary.initial-size=10 spring.datasource.primary.max-active=20 spring.datasource.primary.test-on-borrow=true spring.datasource.primary.test-while-idle=true spring.datasource.primary.validation-query=SELECT 1 FROM DUAL spring.datasource.primary.time-between-eviction-runs-millis=300000 spring.datasource.primary.min-evictable-idle-time-millis=1800000 spring.datasource.second.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.second.url=jdbc:mysql://127.0.0.1:3306/test2?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&useSSL=false&autoReconnect=true&failOverReadOnly=false spring.datasource.second.username=root spring.datasource.second.password=root spring.datasource.second.driverClassName = com.mysql.jdbc.Driver spring.datasource.second.max-wait=10000 spring.datasource.second.max-idle=8 spring.datasource.second.min-idle=8 spring.datasource.second.initial-size=10 spring.datasource.second.max-active=20 spring.datasource.second.test-on-borrow=true spring.datasource.second.test-while-idle=true spring.datasource.second.validation-query=SELECT 1 FROM DUAL spring.datasource.second.time-between-eviction-runs-millis=300000 spring.datasource.second.min-evictable-idle-time-millis=1800000
2.配置完成后需要創建數據源的連接工廠
2.1第一個數據源連接配置
import javax.sql.DataSource; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.SqlSessionTemplate; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; @Configuration //配置mybatis的接口類放的地方 @MapperScan(basePackages = "com.cloud.demo.dao.primary", sqlSessionFactoryRef = "primarySqlSessionFactory") public class DataSourceFirstConfig { // 將這個對象放入Spring容器中 @Bean(name = "primaryDataSource") // 表示這個數據源是默認數據源 @Primary // 讀取application.properties中的配置參數映射成為一個對象 // prefix表示參數的前綴 @ConfigurationProperties(prefix = "spring.datasource.primary") public DataSource getDateSource1() { return DataSourceBuilder.create().build(); } @Bean(name = "primarySqlSessionFactory") // 表示這個數據源是默認數據源 @Primary // @Qualifier表示查找Spring容器中名字為test1DataSource的對象 public SqlSessionFactory test1SqlSessionFactory(@Qualifier("primaryDataSource") DataSource datasource) throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(datasource); bean.setMapperLocations( // 設置mybatis的xml所在位置 new PathMatchingResourcePatternResolver().getResources("classpath*:com/cloud/demo/mapping/primary/*.xml")); return bean.getObject(); } @Bean("primarySqlSessionTemplate") // 表示這個數據源是默認數據源 @Primary public SqlSessionTemplate test1sqlsessiontemplate( @Qualifier("primarySqlSessionFactory") SqlSessionFactory sessionfactory) { return new SqlSessionTemplate(sessionfactory); } }
2.2第二個數據源配連接配置
import javax.sql.DataSource; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.SqlSessionTemplate; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; @Configuration @MapperScan(basePackages = "com.cloud.demo.dao.second", sqlSessionFactoryRef = "secondSqlSessionFactory") public class DataSourceSecondConfig { @Bean(name = "secondDataSource") @ConfigurationProperties(prefix = "spring.datasource.second") public DataSource getDateSource2() { return DataSourceBuilder.create().build(); } @Bean(name = "secondSqlSessionFactory") public SqlSessionFactory test2SqlSessionFactory(@Qualifier("secondDataSource") DataSource datasource) throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(datasource); bean.setMapperLocations( new PathMatchingResourcePatternResolver().getResources("classpath*:com/cloud/demo/mapping/second/*.xml")); return bean.getObject(); } @Bean("secondSqlSessionTemplate") public SqlSessionTemplate test2sqlsessiontemplate( @Qualifier("secondSqlSessionFactory") SqlSessionFactory sessionfactory) { return new SqlSessionTemplate(sessionfactory); } }
PS: @Primary注解一定要配置,否則不知道哪個是默認數據源配置
3.保存切換數據源
public class DataSourceContextHolder { //默認數據源 public static final String DEFAULT_DS = "primaryDataSource"; private static final ThreadLocal<String> contextHolder = new ThreadLocal<>(); // 設置數據源名 public static void setDB(String dbType) { System.out.println("切換到{"+dbType+"}數據源"); contextHolder.set(dbType); } // 獲取數據源名 public static String getDB() { return (contextHolder.get()); } // 清除數據源名 public static void clearDB() { contextHolder.remove(); } }
4.當前數據源
public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { System.out.println("數據源為"+DataSourceContextHolder.getDB()); return DataSourceContextHolder.getDB(); } }
5.創建自定義注解
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface DataSource { String value() default "primaryDataSource"; }
6.使用AOP創建切點
import java.lang.reflect.Method; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; @Aspect @Component public class DynamicDataSourceAspect { @Before("@annotation(DataSource)") public void beforeSwitchDS(JoinPoint point){ //獲得當前訪問的class Class<?> className = point.getTarget().getClass(); //獲得訪問的方法名 String methodName = point.getSignature().getName(); //得到方法的參數的類型 Class[] argClass = ((MethodSignature)point.getSignature()).getParameterTypes(); String dataSource = DataSourceContextHolder.DEFAULT_DS; try { // 得到訪問的方法對象 Method method = className.getMethod(methodName, argClass); // 判斷是否存在@DS注解 if (method.isAnnotationPresent(DataSource.class)) { DataSource annotation = method.getAnnotation(DataSource.class); // 取出注解中的數據源名 dataSource = annotation.value(); } } catch (Exception e) { e.printStackTrace(); } // 切換數據源 DataSourceContextHolder.setDB(dataSource); } @After("@annotation(DataSource)") public void afterSwitchDS(JoinPoint point){ DataSourceContextHolder.clearDB(); } }
7.啟動類修改:
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@MapperScan(basePackages = {"com.cloud.demo.*.dao"})public class TrusteeInterfaceApplication {
public static void main(String[] args) {
SpringApplication.run(TrusteeInterfaceApplication.class, args);
}
}
8.使用方式
只需要在service的實現類中的方法上方使用注解即可
@Override @DataSource("primaryDataSource") public void saveTGLsbrkjg(TgLsbrkjg tgLsbrkjg) { tableMapper.saveTg(tgLsbrkjg); }