在开发中因需求在项目中需要实现多数据源(虽然项目框架是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); }