动态切换多数据源配置,并使用注解切换
- 需要引入的pom坐标
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
- 数据库链接配置
spring:
datasource:
local:
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/data_demo?serverTimezone=UTC&useUnicode=true@characterEncoding=utf-8
remote:
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true@characterEncoding=utf-8
- AbstractRoutingDataSource此类是设置动态数据源的关键,
package datasourc.demo.config;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import javax.sql.DataSource;
import java.util.Map;
public class DynamicDataSource extends AbstractRoutingDataSource {
public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
super.setDefaultTargetDataSource(defaultTargetDataSource);
super.setTargetDataSources(targetDataSources);
}
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceContextHolder.getDataSourceType();
}
}
- 切换数据源的配置
package datasourc.demo.config;
public class DynamicDataSourceContextHolder {
private static ThreadLocal<DataEnum> threadLocal = new ThreadLocal<>();
public static void setDataSourceType(DataEnum type){
threadLocal.set(type);
System.out.println("数据库已经切换"+type);
}
public static DataEnum getDataSourceType(){
return threadLocal.get();
}
public static void clearDatasourceType(){
threadLocal.remove();
}
}
package datasourc.demo.config;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
@Configuration
@MapperScan(basePackages="datasourc.demo.mapper", sqlSessionFactoryRef="sessionFactory")
public class DadaSourceConfig {
@Bean
@ConfigurationProperties("spring.datasource.remote")
public DataSource remoteDateSource(){
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties("spring.datasource.local")
public DataSource localDateSource(){
return DataSourceBuilder.create().build();
}
@Bean
public DataSource dynamicDataSource(@Qualifier("remoteDateSource")DataSource remoteDateSource,@Qualifier("localDateSource")DataSource localDateSource){
Map<Object,Object> datasourceMap = new HashMap<>();
datasourceMap.put(DataEnum.LOCAL,localDateSource);
datasourceMap.put(DataEnum.REMOTE,remoteDateSource);
DynamicDataSource dynamicDataSource = new DynamicDataSource(remoteDateSource, datasourceMap);
return dynamicDataSource;
}
@Bean(name="sessionFactory")
public SqlSessionFactory sessionFactory(@Qualifier("dynamicDataSource")DataSource dataSource) throws Exception{
SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource);
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
sessionFactoryBean.setMapperLocations(resolver.getResources("classpath:mapper/*"));
return sessionFactoryBean.getObject();
}
@Bean(name = "primaryTransactionManager")
public DataSourceTransactionManager primaryTransactionManager(@Qualifier("dynamicDataSource")DataSource dataSource) throws SQLException {
return new DataSourceTransactionManager(dataSource);
}
}
package datasourc.demo.config;
import java.util.HashMap;
import java.util.Map;
public enum DataEnum {
LOCAL,
REMOTE
}
- 引入注解
package datasourc.demo.config;
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
DataEnum value() default DataEnum.LOCAL;
}
- aop增强
package datasourc.demo.config;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
@Aspect
@Order(1)
@Component
public class DataSourceAop {
@Pointcut("@annotation(datasourc.demo.config.DataSource)")
public void dsPointCut() {
}
@Around("dsPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
DataSource dataSource = method.getAnnotation(DataSource.class);
if (dataSource != null) {
DynamicDataSourceContextHolder.setDataSourceType(dataSource.value());
}
try {
return point.proceed();
} finally {
DynamicDataSourceContextHolder.clearDatasourceType();
}
}
}