SpringBoot+Mybatis 동적 데이터 원본 전환

비 즈 니스 배경
전자상거래 주문 항목 은 정방 향 과 역방향 두 부분 으로 나 뉜 다.그 중에서 데이터베이스 에 주문 의 기본 정 보 를 기록 하고 있다.이 는 주문 의 기본 정보,주문 상품 정보,우대 권 정보,영수증 정보,장부 정보,결산 정보,주문 비고 정보,수하인 정보 등 을 포함한다.역방향 데이터 베 이 스 는 주로 상품 의 반품 정보 와 수리 정 보 를 포함한다.데이터 양 이 500 만 줄 을 넘 으 면 라 이브 러 리 분 표 와 읽 기와 쓰기 분 리 를 고려 해 야 한다.그러면 우 리 는 정방 향 조작 과 역방향 조작 을 할 때 해당 하 는 데이터 베 이 스 를 동적 으로 전환 하여 관련 작업 을 해 야 한다.
해결 방향
현재 프로젝트 의 구조 디자인 은 기본적으로 MVC 를 바탕 으로 한다.그러면 데이터 베 이 스 는 dao 층 에 집중 되 어 완성 되 고 주요 업무 논 리 는 service 층 에서 처리 되 며 contrller 층 에서 처리 요청 을 한다.dao 계층 코드 를 실행 하기 전에 데이터 원본(DataSource)을 우리 가 실행 하고 자 하 는 데이터 원본 으로 바 꿀 수 있다 고 가정 하면 이 문 제 는 해 결 됩 니 다.
환경 준비:
1.실체 클래스

@Data
public class Product {    
    private Integer id;    
    private String name;    
    private Double price;
}
2.ProductMapper

public interface ProductMapper { 
    @Select("select * from product") 
    public List<Product> findAllProductM(); 
    @Select("select * from product") 
    public List<Product> findAllProductS(); 
} 
3.ProductService

@Service 
public class ProductService { 
    @Autowired 
    private ProductMapper productMapper; 
    public void findAllProductM(){ 
        //   Master 
        List<Product> allProductM = productMapper.findAllProductM(); 
        System.out.println(allProductM); 
    }
    public void findAllProductS(){ 
        //   Slave 
        List<Product> allProductS = productMapper.findAllProductS(); 
        System.out.println(allProductS); 
    } 
}
구체 적 실현
첫 번 째 단계:다 중 데이터 원본 설정
우선,우 리 는 application.properties 에서 두 개의 데이터 원본 을 설정 합 니 다.

spring.druid.datasource.master.password=root 
spring.druid.datasource.master.username=root 
spring.druid.datasource.master.jdbc- url=jdbc:mysql://localhost:3306/product_master? useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC 
spring.druid.datasource.master.driver-class-name=com.mysql.cj.jdbc.Driver 

spring.druid.datasource.slave.password=root 
spring.druid.datasource.slave.username=root 
spring.druid.datasource.slave.jdbc- url=jdbc:mysql://localhost:3306/product_slave? useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC 
spring.druid.datasource.slave.driver-class-name=com.mysql.cj.jdbc.Driver
 SpringBoot      ,          :

@Configuration 
public class MyDataSourceConfiguratioin { 
    Logger logger = LoggerFactory.getLogger(MyDataSourceConfiguratioin.class); 
    /*** Master data source. */ 
    @Bean("masterDataSource") 
    @ConfigurationProperties(prefix = "spring.druid.datasource.master") 
    DataSource masterDataSource() { 
        logger.info("create master datasource..."); 
        return DataSourceBuilder.create().build(); 
    }

    /*** Slave data source. */ 
    @Bean("slaveDataSource") 
    @ConfigurationProperties(prefix = "spring.druid.datasource.slave") 
    DataSource slaveDataSource() { 
        logger.info("create slave datasource..."); 
        return DataSourceBuilder.create().build(); 
    } 

    @Bean
    @Primary
    DataSource primaryDataSource(@Autowired @Qualifier("masterDataSource")DataSource masterDataSource,

                                 @Autowired @Qualifier("masterDataSource")DataSource slaveDataSource){

        logger.info("create routing datasource..."); 
        Map<Object, Object> map = new HashMap<>(); 
        map.put("masterDataSource", masterDataSource); 
        map.put("slaveDataSource", slaveDataSource); 
        RoutingDataSource routing = new RoutingDataSource(); 
        routing.setTargetDataSources(map); 
        routing.setDefaultTargetDataSource(masterDataSource); 
        return routing; 

    }

}

두 번 째 단계:RoutingDataSource 작성
그 다음 에 우 리 는 Spring 에 내 장 된 RoutingDataSource 로 두 개의 실제 데이터 소스 를 동적 데이터 소스 로 대리 합 니 다.

public class RoutingDataSource extends AbstractRoutingDataSource { 
    @Override 
    protected Object determineCurrentLookupKey() { 
        return RoutingDataSourceContext.getDataSourceRoutingKey();
    } 
} 
세 번 째 단계:RoutingDataSource Context 작성
현재 데이터 원본 으로 전환 할 데이터 원본 을 저장 하 는 데 사용 합 니 다.

public class RoutingDataSourceContext { 
    // holds data source key in thread local: 
    static final ThreadLocal<String> threadLocalDataSourceKey = new ThreadLocal<>(); 
    public static String getDataSourceRoutingKey() { 
        String key = threadLocalDataSourceKey.get(); 
        return key == null ? "masterDataSource" : key; 
    }
    public RoutingDataSourceContext(String key) { 
        threadLocalDataSourceKey.set(key); 
    }
    public void close() { 
        threadLocalDataSourceKey.remove(); 
    }
}
테스트(코드 는 controller 의 코드 입 니 다)

@GetMapping("/findAllProductM")
public String findAllProductM() {    
    String key = "masterDataSource";    
    RoutingDataSourceContext routingDataSourceContext = new RoutingDataSourceContext(key);    
    productService.findAllProductM();    
    return "master";
}
@GetMapping("/findAllProductS")
public String findAllProductS() {    
    String key = "slaveDataSource";
    RoutingDataSourceContext routingDataSourceContext = new RoutingDataSourceContext(key);
    productService.findAllProductS();
    return "slave";
}
이상 코드 는 데이터 원본 동적 전환 을 실현 할 수 있 습 니 다.
최적화:
상기 코드 는 실행 가능 하지만 데이터 베 이 스 를 읽 어야 하 는 곳 에 RoutingDataSourceContext 를 추가 해 야 합 니 다.
ctx=...코드,사용 하기에 매우 불편 합 니 다.다음은 최적화 방안 이다.
위 RoutingDataSourceContext 의 값 을 주해 의 value 속성 에 넣 고 사용자 정의 주 해 를 설명 할 수 있 습 니 다.
그 다음 에 절단면 류 를 정의 합 니 다.우리 가 방법 에 사용자 정의 주 해 를 표시 할 때 절단면 논 리 를 실행 하여 주해 중의 값 을 얻 고 set 를 RoutingDataSourceContext 에 가 져 와 주 해 를 통 해 데이터 원본 을 동적 으로 전환 합 니 다.
다음은 코드 구현:
주해 류

@Target(ElementType.METHOD) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface RoutingWith {
 String value() default "master";
 }
절단면 종류:

@Aspect 
@Component 
public class RoutingAspect {
 @Around("@annotation(routingWith)")
 public Object routingWithDataSource(ProceedingJoinPoint joinPoint, RoutingWith routingWith) throws Throwable {
     String key = routingWith.value();
     RoutingDataSourceContext ctx = new RoutingDataSourceContext(key);
     return joinPoint.proceed();
 }
} 
컨트롤 러 방법 개조

@RoutingWith("masterDataSource") 
@GetMapping("/findAllProductM") 
public String findAllProductM() {
 productService.findAllProductM(); return "lagou"; 
}

@RoutingWith("slaveDataSource") 
@GetMapping("/findAllProductS") 
public String findAllProductS() {
  productService.findAllProductS(); return "lagou";
 }

SpringBoot+Mybatis 가 동적 데이터 원본 전환 을 실현 하 는 것 에 대한 상세 한 설명 은 여기까지 입 니 다.SpringBoot+Mybatis 동적 데이터 원본 전환 에 관 한 더 많은 내용 은 저희 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 저 희 를 많이 응원 해 주세요!

좋은 웹페이지 즐겨찾기