Springboot動的切替データソース+jpa
6518 ワード
1、アプリケーション-dev.properties構成
2、異なる要求、異なるスレッド、データソースの隔離クラス
3、spring公式AbstractRoutingDataSourceコアクラス実現
4、定数配置
5、データソースの構成
6、aop注釈により、データソースを動的に切り替える
7、動的切替データソース、例
コントローラの例
サービスの例
トランザクション制御、参照可能https://www.cnblogs.com/jpfss/p/8295692.html
spring.datasource.primary.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.primary.jdbc-url=jdbc:mysql:///project_datahub?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
spring.datasource.primary.username=root
spring.datasource.primary.password=root
spring.datasource.secondary.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.secondary.jdbc-url=jdbc:mysql:///project_datahub_second?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
spring.datasource.secondary.username=root
spring.datasource.secondary.password=root
2、異なる要求、異なるスレッド、データソースの隔離クラス
/**
* @Description
* @Author lxk
* @version V1.0.0
*/
public class DBContextHolder{
/**
* ThreadLocal , , ,
*/
private static final ThreadLocal CONTEXT_HOLDER = new ThreadLocal<>();
public static void setDataSource(String dataSource) {
CONTEXT_HOLDER.set(dataSource);
}
public static String getDataSource() {
return CONTEXT_HOLDER.get();
}
public static void clearDataSource() {
CONTEXT_HOLDER.remove();
}
}
3、spring公式AbstractRoutingDataSourceコアクラス実現
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import org.springframework.lang.Nullable;
public class MyRoutingDataSource extends AbstractRoutingDataSource {
@Nullable
@Override
protected Object determineCurrentLookupKey() {
return DBContextHolder.getDataSource();
}
}
4、定数配置
/**
* @Description
* @Author lxk
* @version V1.0.0
*/
public interface DataSourceNames {
String FIRST = "first";
String SECOND = "second";
}
5、データソースの構成
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.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
/**
* @Description
* @Author lxk
* @version V1.0.0
*/
@Configuration
public class DataSourceConfig {
@Bean(name = "firstDataSource")
@Qualifier("firstDataSource")
@ConfigurationProperties(prefix="spring.datasource.primary")
public DataSource firstDataSource() {
System.out.println("primary db built");
return DataSourceBuilder.create().build();
}
@Bean(name = "secondDataSource")
@Qualifier("secondDataSource")
@ConfigurationProperties(prefix="spring.datasource.secondary")
public DataSource secondDataSource() {
System.out.println("secondary db built");
return DataSourceBuilder.create().build();
}
@Primary
@Bean
public DataSource dataSource(DataSource firstDataSource, DataSource secondDataSource) {
Map
6、aop注釈により、データソースを動的に切り替える
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.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
* ,
* @Author lxk
* @version V1.0.0
*/
@Aspect
@Component
public class DataSourceAspect implements Ordered {
@Pointcut("@annotation(com.magus.datahub.master.orghandler.config.CurDataSource)")
public void dataSourcePointCut() {
}
@Before("dataSourcePointCut()")
public void doBefore(JoinPoint point){
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
CurDataSource ds = method.getAnnotation(CurDataSource.class);
if (ds == null) {
DBContextHolder.setDataSource(DataSourceNames.FIRST);
} else {
DBContextHolder.setDataSource(ds.name());
}
}
@After("dataSourcePointCut()")
public void after(JoinPoint point) {
// ,
DBContextHolder.clearDataSource();
}
@Override
public int getOrder() {
return -1;
}
}
7、動的切替データソース、例
コントローラの例
@RequestMapping("/ehr")
public class EhrController {
@Autowired
private EhrService ehrService;
@GetMapping("/test/switch")
public ResponseEntity> ehrServiceSwitch(){
return ResponseEntity.ok(ehrService.findAllSwitch());
}
@GetMapping("/test")
public ResponseEntity> ehrService(){
return ResponseEntity.ok(ehrService.findAll());
}
}
サービスの例
@Service
public class EhrService {
@Autowired
private MasterCompanyRepository companyRepository;
public List findAll(){
return companyRepository.findAll();
}
@CurDataSource(name = DataSourceNames.SECOND)
public List findAllSwitch(){
return companyRepository.findAll();
}
}
トランザクション制御、参照可能https://www.cnblogs.com/jpfss/p/8295692.html