springboot+my batis 설정 다 중 데이터 원본 예제

12142 단어 springboot
실제 개발 에서 우리 의 한 프로젝트 는 여러 개의 데이터 베 이 스 를 사용 할 수 있 고 보통 하나의 데이터 베 이 스 는 하나의 데이터 소스 에 대응 할 수 있다.
코드 구조:

간단 한 원리:
1)DatabaseType 은 모든 데이터 원본 의 key-key 를 보 여 줍 니 다.
2)Database ContextHolder 는 안전 한 라인 의 Database Type 용기 로 데이터베이스 Type 을 설정 하고 가 져 오 는 방법 을 제공한다
3)DynamicDataSource 는 AbstractRouting DataSource 를 계승 하여 그 방법 을 다시 작성 합 니 다 determineCurrentLookupkey().이 방법 에서 DatabaseContextHolder 를 사용 하여 현재 스 레 드 의 DatabaseType 을 가 져 옵 니 다.
4)MyBatisConfig 에서 데이터 원본 DataSource 의 bean-value 2 개 생 성
5)MyBatisConfig 에서 1)과 4)로 구 성 된 key-value 는 DynamicDataSource 동적 데이터 원본 에 기 록 된 targetDataSources 속성(물론,2 개의 데이터 원본 중 하 나 는 DynamicDataSource 의 default TargetDataSource 속성 중)을 설정 합 니 다.
6)DynamicDataSource 를 primary 데이터 원본 으로 SqlSession Factory 의 dataSource 속성 에 주입 하고 이 dataSource 를 transactionManager 의 입 참 으로 DataSource TransactionManager 를 구성 합 니 다.
7)사용 시 dao 층 이나 service 층 에서 Database ContextHolder 설정 을 사용 하여 사용 할 데이터 원본 key 를 사용 한 다음 에 mapper 층 을 호출 하여 해당 하 는 작업 을 하 는 것 을 권장 합 니 다.dao 층 에 두 는 것 을 권장 합 니 다(물론 spring op+자체 주 해 를 사용 할 수도 있 습 니 다)
메모:mapper 층 에서 작업 을 할 때 determineCurrentLookupkey()방법 으로 데이터 원본 을 가 져 옵 니 다(데이터 원본 가 져 오기:설정 에 따라 targetDataSources 에서 찾 고 없 으 면 default TargetDataSource 를 선택 합 니 다).그 다음 에 데이터 라 이브 러 리 작업 을 합 니 다.
 1.두 개의 데이터베이스 가 있다 고 가정 하면 다음 과 같이 설정 합 니 다.
application.properties

#the first datasource
jdbc.driverClassName = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://xxx:3306/mytestdb?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8
jdbc.username = root
jdbc.password = 123

#the second datasource
jdbc2.driverClassName = com.mysql.jdbc.Driver
jdbc2.url = jdbc:mysql://xxx:3306/mytestdb2?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8
jdbc2.username = root
jdbc2.password = 123

설명:이전 설정 을 바탕 으로 상기 두 번 째 데이터 원본 만 추 가 했 습 니 다. 
2、DatabaseType

package com.xxx.firstboot.common.datasource;

/**
 *         key(          )
 *   :
 * 1)              
 * 2)DatabaseType              
 */
public enum DatabaseType {
  mytestdb,mytestdb2
}

역할:데이터 원본 키 를 열거 합 니 다.
3、DatabaseContextHolder

package com.xxx.firstboot.common.datasource;

/**
 *   :
 * 1、         DatabaseType  
 */
public class DatabaseContextHolder {
  private static final ThreadLocal<DatabaseType> contextHolder = new ThreadLocal<>();
  
  public static void setDatabaseType(DatabaseType type){
    contextHolder.set(type);
  }
  
  public static DatabaseType getDatabaseType(){
    return contextHolder.get();
  }
}

역할:DatabaseType 용 기 를 구축 하고 DatabaseType 을 설정 하고 가 져 오 는 방법 을 제공 합 니 다.
4、DynamicDataSource

package com.xxx.firstboot.common.datasource;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

/**
 *      (    AbstractRoutingDataSource)
 */
public class DynamicDataSource extends AbstractRoutingDataSource {
  protected Object determineCurrentLookupKey() {
    return DatabaseContextHolder.getDatabaseType();
  }
}

역할:DatabaseContextHolder 를 사용 하여 현재 스 레 드 의 DatabaseType 가 져 오기 
5、MyBatisConfig

package com.xxx.firstboot.common;

import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.xxx.firstboot.common.datasource.DatabaseType;
import com.xxx.firstboot.common.datasource.DynamicDataSource;

/**
 * springboot  mybatis      1)     (         tomcat-jdbc   ,    )
 * 2)  SqlSessionFactory 3)       ,        ,      
 */
@Configuration //       spring    
@MapperScan(basePackages = "com.xxx.firstboot.mapper")
public class MyBatisConfig {

  @Autowired
  private Environment env;

  /**
   *      (      :       XXXDataSource(),XXX      ,            )
   */
  @Bean
  public DataSource myTestDbDataSource() throws Exception {
    Properties props = new Properties();
    props.put("driverClassName", env.getProperty("jdbc.driverClassName"));
    props.put("url", env.getProperty("jdbc.url"));
    props.put("username", env.getProperty("jdbc.username"));
    props.put("password", env.getProperty("jdbc.password"));
    return DruidDataSourceFactory.createDataSource(props);
  }

  @Bean
  public DataSource myTestDb2DataSource() throws Exception {
    Properties props = new Properties();
    props.put("driverClassName", env.getProperty("jdbc2.driverClassName"));
    props.put("url", env.getProperty("jdbc2.url"));
    props.put("username", env.getProperty("jdbc2.username"));
    props.put("password", env.getProperty("jdbc2.password"));
    return DruidDataSourceFactory.createDataSource(props);
  }

  /**
   * @Primary                         ,       ,    @autowire    
   * @Qualifier         ,                     (     DataSource     )
   */
  @Bean
  @Primary
  public DynamicDataSource dataSource(@Qualifier("myTestDbDataSource") DataSource myTestDbDataSource,
      @Qualifier("myTestDb2DataSource") DataSource myTestDb2DataSource) {
    Map<Object, Object> targetDataSources = new HashMap<>();
    targetDataSources.put(DatabaseType.mytestdb, myTestDbDataSource);
    targetDataSources.put(DatabaseType.mytestdb2, myTestDb2DataSource);

    DynamicDataSource dataSource = new DynamicDataSource();
    dataSource.setTargetDataSources(targetDataSources);//     AbstractRoutingDataSource   
    dataSource.setDefaultTargetDataSource(myTestDbDataSource);//    datasource   myTestDbDataSource

    return dataSource;
  }

  /**
   *        SqlSessionFactory
   */
  @Bean
  public SqlSessionFactory sqlSessionFactory(DynamicDataSource ds) throws Exception {
    SqlSessionFactoryBean fb = new SqlSessionFactoryBean();
    fb.setDataSource(ds);//      (     ,    )
    //         *.xml  ,               xml    (         ),   
    fb.setTypeAliasesPackage(env.getProperty("mybatis.typeAliasesPackage"));//     
    fb.setMapperLocations(
        new PathMatchingResourcePatternResolver().getResources(env.getProperty("mybatis.mapperLocations")));//

    return fb.getObject();
  }

  /**
   *        
   */
  @Bean
  public DataSourceTransactionManager transactionManager(DynamicDataSource dataSource) throws Exception {
    return new DataSourceTransactionManager(dataSource);
  }

}

역할:
  • application.properties 파일 을 읽 어서 두 개의 데이터 원본(my TestDbDataSource,my TestDb2dataSource)을 생 성 합 니 다
  • 이상 에서 생 성 된 두 개의 데이터 소스 구조 동적 데이터 소스 dataSource 를 사용 합 니 다.
  • @Primary:같은 인터페이스 에 여러 개의 실현 클래스 가 주입 할 수 있 는 지 지정 할 때 기본 값 으로 어떤 것 을 선택 하 는 지 지정 합 니 다.@Autowire 에 오 류 를 표시 하 는 것 이 아 닙 니 다(일반적으로 다 중 데이터 소스 에 사용 되 는 경우)
  • @Qualifier:이름 의 주입 을 지정 합 니 다.한 인터페이스 에 여러 개의 실현 클래스 가 있 을 때 사용 합 니 다(이 예 에서 DataSource 형식의 인 스 턴 스 가 두 개 있 습 니 다.이름 을 지정 하여 주입 해 야 합 니 다)
  • @Bean:생 성 된 bean 인 스 턴 스 의 이름 은 방법 명(예 를 들 어 위의@Qualifier 주석 에서 사용 하 는 이름 은 앞의 두 데이터 소스 의 방법 명 이 고 이 두 데이터 소스 도@Bean 주석 으로 주입 한 것)
  • 동적 데이터 소스 를 통 해 SqlSession Factory 와 사무 관리자(사무 가 필요 하지 않 으 면 후 자 는 제거 할 수 있 습 니 다)
  •  6.사용
    ShopMapper:
    
    package com.xxx.firstboot.mapper;
    
    import org.apache.ibatis.annotations.Param;
    import org.apache.ibatis.annotations.Result;
    import org.apache.ibatis.annotations.Results;
    import org.apache.ibatis.annotations.Select;
    
    import com.xxx.firstboot.domain.Shop;
    
    public interface ShopMapper {
    
      @Select("SELECT * FROM t_shop WHERE id = #{id}")
      @Results(value = { @Result(id = true, column = "id", property = "id"),
                @Result(column = "shop_name", property = "shopName") })
      public Shop getShop(@Param("id") int id);
    
    }
    
    
    ShopDao:
    
    package com.xxx.firstboot.dao;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Repository;
    
    import com.xxx.firstboot.common.datasource.DatabaseContextHolder;
    import com.xxx.firstboot.common.datasource.DatabaseType;
    import com.xxx.firstboot.domain.Shop;
    import com.xxx.firstboot.mapper.ShopMapper;
    
    @Repository
    public class ShopDao {
      @Autowired
      private ShopMapper mapper;
    
      /**
       *   shop
       */
      public Shop getShop(int id) {
        DatabaseContextHolder.setDatabaseType(DatabaseType.mytestdb2);
        return mapper.getShop(id);
      }
    }
    
    
    메모:먼저 데이터 원본 의 key 를 설정 한 다음 mapper 를 호출 합 니 다.(mapper 에서 먼저 이 key 에 따라 동적 데이터 원본 에서 해당 하 는 데이터 원본 을 조회 한 다음 연결 을 꺼 내 데이터베이스 작업 을 합 니 다)
    ShopService:
    
    package com.xxx.firstboot.service;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import com.xxx.firstboot.dao.ShopDao;
    import com.xxx.firstboot.domain.Shop;
    
    @Service
    public class ShopService {
    
      @Autowired
      private ShopDao dao;
    
      public Shop getShop(int id) {
        return dao.getShop(id);
      }
    }
    
    
    ShopController:
    
    package com.xxx.firstboot.web;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    
    import com.xxx.firstboot.domain.Shop;
    import com.xxx.firstboot.service.ShopService;
    
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiOperation;
    
    @RestController
    @RequestMapping("/shop")
    @Api("shopController  api")
    public class ShopController {
    
      @Autowired
      private ShopService service;
    
      @ApiOperation("  shop  ,      ")
      @RequestMapping(value = "/getShop", method = RequestMethod.GET)
      public Shop getShop(@RequestParam("id") int id) {
        return service.getShop(id);
      }
    
    }
    
    
    보:사실 Database ContextHolder 와 DynamicDataSource 는 하나의 클래스 로 완전히 합 칠 수 있 습 니 다.
    이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기