구조에 대한 소감-mybatis 여러 개의 데이터 원본을 start 패키지로 사용

선언:
최근에 프로젝트를 새로 만들었습니다. 여러 개의 데이터 원본을 사용하고 동적 전환이 필요합니다. 그래서 데이터 원본을 전환하는 starter 패키지를 썼습니다.
spring-boot-starter-multiple-data-source

두 데이터 원본을 읽기와 쓰기로 분리하는 예
하나.데이터 소스 구성
여러 데이터 소스 구성
spring:
    datasource:
        master:
          jdbc-url: jdbc:mysql://127.0.0.1:3306/demo1?useUnicode=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2b8&useSSL=false
          username: xxxxxxxxx
          password: xxxxxxxxx
          driver-class-name: com.mysql.cj.jdbc.Driver
        slave:
          jdbc-url: jdbc:mysql://127.0.0.1:3306/demo2?useUnicode=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2b8&useSSL=false
          username: xxxxxx
          password: xxxxxx
          driver-class-name: com.mysql.cj.jdbc.Driver

기본 클래스:
DataSourceType.java 데이터 소스 매개 클래스
public enum DataSourceType {

    MASTER("master"),
    SLAVE("slave");

    private String dataSource;

    DataSourceType(String dataSource){
        this.dataSource = dataSource;
    }

    public String getDataSource() {
        return dataSource;
    }
}

MybatisConfig 클래스:
여러 개의 데이터 원본을 불러오고 기본 데이터 원본은 마스터입니다
@Configuration
@MapperScan(basePackages = {"**.*Mapper"}) //   DAO
public class MybatisConfig {


    @Bean("master")
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource.master")
    public DataSource master(){
        return DataSourceBuilder.create().build();
    }

    @Bean("slave")
    @ConfigurationProperties(prefix = "spring.datasource.slave")
    public DataSource slave(){
        return DataSourceBuilder.create().build();
    }

    @Bean("dynamicDataSource")
    public DataSource dynamicDataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        Map dataSourceMap = new HashMap<>(2);
        dataSourceMap.put(DataSourceType.MASTER.getDataSource(), master());
        dataSourceMap.put(DataSourceType.SLAVE.getDataSource(), slave());
        //   master              
        dynamicDataSource.setDefaultDataSource(master());
        //   master   slave            
        dynamicDataSource.setDataSources(dataSourceMap);
        return dynamicDataSource;
    }

    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean() throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        //      ,         ,      dynamicDataSource            
        sessionFactory.setDataSource(dynamicDataSource());
        //   Model
        //sessionFactory.setTypeAliasesPackage("com.danke.**.entity");
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        //       
        sessionFactory.setMapperLocations(resolver.getResources("**.*Mapper.xml"));
        return sessionFactory;
    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        //       ,             @Transactional    
        return new DataSourceTransactionManager(dynamicDataSource());
    }
}

상하문 클래스, 라인 안전 확보에 사용
public class DynamicDataSourceContextHolder {

    private static final ThreadLocal contextHolder = new ThreadLocal() {
        /**
         *   master      key         key
         */
        @Override
        protected String initialValue() {
            return DataSourceType.MASTER.getDataSource();
        }
    };


    /**
     *      key  ,              
     */
    public static List dataSourceKeys = new ArrayList<>();

    /**
     *      
     * @param key
     */
    public static void setDataSourceKey(String key) {
        contextHolder.set(key);
    }

    /**
     *      
     * @return
     */
    public static String getDataSourceKey() {
        return contextHolder.get();
    }

    /**
     *      
     */
    public static void clearDataSourceKey() {
        contextHolder.remove();
    }

    /**
     *          
     * @param key    key
     * @return
     */
    public static boolean containDataSourceKey(String key) {
        return dataSourceKeys.contains(key);
    }

    /**
     *      keys
     * @param keys
     * @return
     */
    public static boolean addDataSourceKeys(Collection extends Object> keys) {
        return dataSourceKeys.addAll(keys);
    }

}

TargetDataSource.java 주석 클래스
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TargetDataSource {

    /**
     *    key 
     * @return
     */
    DataSourceType value();

}

탄젠트 동적 전환 데이터 소스
@Slf4j
@Aspect
@Order(-1)
@Component
public class DynamicDataSourceAspect {

    /**
     *      
     * @param point
     * @param targetDataSource
     */
    @Before("@annotation(targetDataSource))")
    public void switchDataSource(JoinPoint point, TargetDataSource targetDataSource) {
        if (!DynamicDataSourceContextHolder.containDataSourceKey(targetDataSource.value().getDataSource())) {
            log.info("    【{}】    ,         【{}】 " + targetDataSource.value());
        } else {
            //      
            DynamicDataSourceContextHolder.setDataSourceKey(targetDataSource.value().getDataSource());
            log.info("     【" + DynamicDataSourceContextHolder.getDataSourceKey()
                    + "】    【" + point.getSignature() + "】");
        }
    }

    /**
     *      
     * @param point
     * @param targetDataSource
     */
    @After("@annotation(targetDataSource))")
    public void restoreDataSource(JoinPoint point, TargetDataSource targetDataSource) {
        //            
        DynamicDataSourceContextHolder.clearDataSourceKey();
        log.info("       【" + DynamicDataSourceContextHolder.getDataSourceKey()
                + "】     【" + point.getSignature() + "】");
    }
}

여기 모든 설정이 완료되었습니다
적용:
springboot 시작 클래스에 추가해야 합니다
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})

첫 번째:
starter 패키지에 META-INF/spring을 추가합니다.factories 파일:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
xxx.xxx.xxx.MybatisConfig

프로젝트에 도입된jar 패키지는 자동으로 MybatisConfig 파일을 로드합니다.
두 번째:
프로젝트에 MybatisConfig 클래스 통합 starter 패키지의 MybatisConfig 추가
다음 코드:
@Configuration
public class MybatisConfig extends xxx.xxx.xxx.MybatisConfig{
}

데이터 소스 전환 사용, 방법상 @TargetDataSource 식별
    @TargetDataSource(DataSourceType.SLAVE)
    @Override
    public void selectById(Integer id) {
       //  slave   
    }
    
    @TargetDataSource(DataSourceType.MASTER)
    @Override
    public void updateById(String str) {
        //  master   
    }

세 번째:
이런 방식도springboot에서 현재 사용하고 있는 것으로 어떠한 설정도 필요 없고 주석만 있습니다
새 메모 클래스
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(MybatisConfig.class)
public @interface MultipleDataSource {
}

그리고 시작 클래스에 주석을 달아주세요.
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@EnableDiscoveryClient
@MultipleDataSource//      
public class Application {
  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }
}

좋은 웹페이지 즐겨찾기