mybatis多数据源切换--AOP实现
- 方案
- 代码
- 1.配置相关
- pom.xml
- yml文件
- yml对应配置类
- 数据源配置类
- 数据源切换类
- 动态数据源类(重点)
- 2.aop
-
方案
- AOP+注解:适用于方法级的数据源动态切换
- 分包法(生成多个SqlSessionFactory,分别指定不同的mapper包)
这里我先介绍常用的方式:AOP+注解
代码
1.配置相关
pom.xml
<dependency><groupId>org.springframework.bootgroupId><artifactId>spring-boot-starter-webartifactId>dependency><dependency><groupId>org.springframework.bootgroupId><artifactId>spring-boot-starter-aopartifactId>dependency><dependency><groupId>com.alibabagroupId><artifactId>druid-spring-boot-starterartifactId><version>1.2.6version>dependency><dependency><groupId>org.mybatis.spring.bootgroupId><artifactId>mybatis-spring-boot-starterartifactId><version>2.1.4version>dependency><dependency><groupId>mysqlgroupId><artifactId>mysql-connector-javaartifactId><version>8.0.24version>dependency><dependency><groupId>org.projectlombokgroupId><artifactId>lombokartifactId><optional>trueoptional>dependency>
yml文件
mybatis:type-aliases-package: com.jenkins.domainmapper-locations: classpath*:/mapper/*.xmlspring:datasource:type: com.alibaba.druid.pool.DruidDataSourcedbs:db1:url: jdbc:mysql://ip:3306/db1?useSSL=false&serverTimezone=UTCusername: rootpassword: admindriver-class-name: com.mysql.cj.jdbc.Driverdb2:url: jdbc:mysql://ip:3306/db2?useSSL=false&serverTimezone=UTCusername: rootpassword: admindriver-class-name: com.mysql.cj.jdbc.Driver
yml对应配置类
@Data
@Configuration
@ConfigurationProperties(prefix = "spring.datasource")
public class DbConfig {private Map<String, DruidDataSource> dbs;
}
数据源配置类
@Configuration
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class DynamicDataSourceConfig {private final DbConfig dbConfig;@Bean("dynamicDataSource")public DynamicDataSource dynamicDataSource() {Map<Object, Object> dataSourceMap = new HashMap<>();dbConfig.getDbs().forEach(dataSourceMap::put);DynamicDataSource dynamicDataSource = new DynamicDataSource();dynamicDataSource.setTargetDataSources(dataSourceMap);dynamicDataSource.setDefaultTargetDataSource(dbConfig.getDbs().get("db1"));return dynamicDataSource;}}
数据源切换类
public class DynamicDataSourceContextHolder {public static final String DS1_KEY = "db1";public static final String DS2_KEY = "db2";private static final ThreadLocal<String> DATASOURCE_CONTEXT_KEY = new ThreadLocal<>();public static void setContextKey(String key) {DATASOURCE_CONTEXT_KEY.set(key);}public static String getContextKey() {String key = DATASOURCE_CONTEXT_KEY.get();return key == null ? DS1_KEY : key;}public static void removeContextKey() {DATASOURCE_CONTEXT_KEY.remove();}
}
动态数据源类(重点)
public class DynamicDataSource extends AbstractRoutingDataSource {@Overrideprotected Object determineCurrentLookupKey() {return DynamicDataSourceContextHolder.getContextKey();}
}
2.aop
注解
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {String value();
}
切面
@Aspect
@Component
public class DataSourceAspect {@Pointcut("@annotation(com.hui.annotations.DataSource)")public void pointCut() {}@Around("pointCut()")public Object around(ProceedingJoinPoint joinPoint) throws Throwable {String dsKey = getDSAnnotation(joinPoint).value();DynamicDataSourceContextHolder.setContextKey(dsKey);try {return joinPoint.proceed();} finally {DynamicDataSourceContextHolder.removeContextKey();}}private DataSource getDSAnnotation(ProceedingJoinPoint joinPoint) {Class<?> targetClass = joinPoint.getTarget().getClass();DataSource dsAnnotation = targetClass.getAnnotation(DataSource.class);if (Optional.ofNullable(dsAnnotation).isPresent()) {return dsAnnotation;} else {MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();return methodSignature.getMethod().getAnnotation(DataSource.class);}}
}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!