spring boot my batis 다 중 데이터 원본
spring boot 프로젝트 에서 시스템 기본 값 은 applicationContext 에 dataSource 의 bean 을 자동 으로 등록 합 니 다. DataSource. class 의 인 스 턴 스 를 정의 하면 이 bean 을 덮어 씁 니 다.그러나 여러 개의 DataSource. class 인 스 턴 스 를 정의 하면 시작 할 때 실례 화 된 mapper 를 제시 할 때 여러 개의 datasource 를 발견 하여 시작 에 실 패 했 습 니 다.
먼저 단일 데이터 원본 의 설정 사례 를 살 펴 보 겠 습 니 다.
1. 단일 데이터 소스 현황
1.1、MyBatisConfiguration
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
@Configuration
@ConditionalOnClass({EnableTransactionManagement.class})
@MapperScan(basePackages={"com.roy.**.mapper"})
public class MyBatisConfiguration {
@Autowired
private DataSource dataSource;
public DataSource dataSource() {
return dataSource;
}
@Bean(name = "sqlSessionFactory")
public SqlSessionFactory sqlSessionFactoryBean() throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource());
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath:/mybatis/**/*.xml"));
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
configuration.setMapUnderscoreToCamelCase(true);
sqlSessionFactoryBean.setConfiguration(configuration);
return sqlSessionFactoryBean.getObject();
}
@Bean
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) { return new SqlSessionTemplate(sqlSessionFactory); }
@Bean(name = "transactionManager")
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
}
1.2、application.properties
#
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driverClassName=oracle.jdbc.driver.OracleDriver
spring.datasource.url=jdbc:oracle:thin:@//127.0.0.1:1521/testdb
spring.datasource.username=test
spring.datasource.password=test
# ,
# , ,
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
#
spring.datasource.maxWait=60000
# , ,
spring.datasource.timeBetweenEvictionRunsMillis=60000
# ,
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=SELECT 1 FROM DUAL
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
# PSCache, PSCache
spring.datasource.poolPreparedStatements=true
spring.datasource.maxPoolPreparedStatementPerConnectionSize=20
# filters, sql ,'wall'
spring.datasource.filters=stat,wall,log4j
# connectProperties mergeSql ; SQL
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
# DruidDataSource
#spring.datasource.useGlobalDataSourceStat=true
다 중 데이터 소스 다 중 데이터 소스 로 개조 하 는 주요 실현 원 리 는 DataSource 인터페이스의 실현, getConnection () 과 unwrap () 방법 을 재 작성 하 는 것 입 니 다. 여기 서 다 중 데이터 소스 datasource 에 대한 선택 전환 을 실현 하고 SqlSession Factory 와 PlatformTransactionManager 에 등록 합 니 다.저 희 는 AbstractRouting DataSource 류 를 참고 하여 여러 datasource 의 기능 을 지원 하 는 것 을 발 견 했 습 니 다. 저 희 는 proctected abstract Object determineCurrentLookupkey () 만 실현 하면 됩 니 다.방법 으로 datasource 를 전환 하면 됩 니 다.이 를 위해 우 리 는 인터넷 예 를 참고 하여 위의 단일 데이터 소스 를 다음 과 같이 조정 하여 다 중 데이터 소스 를 지원 합 니 다.
2. 다 중 데이터 소스 현황
2.1 새로운 DynamicDataSource 클래스 계승 AbstractRoutingDataSource
public class DynamicDataSource extends AbstractRoutingDataSource {
protected Object determineCurrentLookupKey() {
return DatabaseContextHolder.getDatabaseName();
}
}
2.2, 새 DatabaseContextHolder, 스 레 드 변 수 를 이용 하여 현재 데이터 원본 의 key 값 을 저장 합 니 다 (여기 서 dataSource 인 스 턴 스 의 beanName 을 key 값 으로 사용 합 니 다)
public class DatabaseContextHolder {
private static final ThreadLocal contextHolder = new ThreadLocal<>();
public static void setDatabaseName(String type){
contextHolder.set(type);
}
public static String getDatabaseName(){
return contextHolder.get();
}
public static void clear() {
contextHolder.remove();
}
}
2.3 위의 MyBatisConfiguration 클래스 를 개조 하고 dataSource () 방법 을 다시 씁 니 다.
@Autowired
private DataSource dataSource;
public Map otherDataSources() {
return null;
}
public DataSource dataSource() {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
Map
주의: 여기 서 저 는 인터넷 에서 여러 개의 DataSource. class 의 bean 을 applicationContext 로 예화 하 는 방식 을 사용 하지 않 았 습 니 다. 제 실제 검증 을 통 해 applicationContext 안에 여러 개의 DataSource. class 의 bean 이 있 으 면 mapper 의 bean 을 생산 할 때 모두 잘못 보고 할 수 있 습 니 다 (제 구조 상 어디 에 제한 이 있 는 지 모 르 는 것 일 수도 있 습 니 다).그래서 저 는 특별한 방식 으로 Public Map otherDataSources () {return null;} 의 방법 을 추 가 했 습 니 다. 여러 개의 DataSource 가 있 으 면 이 안에 new 가 나 오고 applicationContext 에 주입 되 지 않 습 니 다.
2.4. DataSource 를 어떻게 자체 적 으로 예화 하 는 지 다음 과 같은 것 을 참고 하 십시오. 여기 서 저 희 는 DruidDataSource 를 사용 합 니 다.
@Value("${second.datasource.url}")
private String dbUrl;
@Value("${second.datasource.username}")
private String username;
@Value("${second.datasource.password}")
private String password;
@Autowired
protected DataSourceProperties dataSourceProperties;
public static final String DATASOURCE_SECOND_KEY="secondDataSource";
public Map otherDataSources() {
Map map = new HashMap<>();
map.put(DATASOURCE_SECOND_KEY, secondDataSource());
return map;
}
public DataSource secondDataSource() {
DruidDataSource datasource = new DruidDataSource();
datasource.setUrl(dbUrl);
datasource.setUsername(username);
datasource.setPassword(password);
datasource.setDriverClassName(dataSourceProperties.getDriverClassName());
datasource.setInitialSize(dataSourceProperties.getInitialSize());
datasource.setMinIdle(dataSourceProperties.getMinIdle());
datasource.setMaxActive(dataSourceProperties.getMaxActive());
datasource.setMaxWait(dataSourceProperties.getMaxWait());
datasource.setTimeBetweenEvictionRunsMillis(dataSourceProperties.getTimeBetweenEvictionRunsMillis());
datasource.setMinEvictableIdleTimeMillis(dataSourceProperties.getMinEvictableIdleTimeMillis());
datasource.setValidationQuery(dataSourceProperties.getValidationQuery());
if (dataSourceProperties.getTestWhileIdle()!=null) {
datasource.setTestWhileIdle(dataSourceProperties.getTestWhileIdle());
}
if (dataSourceProperties.getTestOnBorrow()!=null){
datasource.setTestOnBorrow(dataSourceProperties.getTestOnBorrow());
}
if (dataSourceProperties.getTestOnReturn()!=null) {
datasource.setTestOnReturn(dataSourceProperties.getTestOnReturn());
}
if (dataSourceProperties.getPoolPreparedStatements()!=null) {
datasource.setPoolPreparedStatements(dataSourceProperties.getPoolPreparedStatements());
}
if (dataSourceProperties.getMaxPoolPreparedStatementPerConnectionSize()!=null) {
datasource.setMaxPoolPreparedStatementPerConnectionSize(dataSourceProperties.getMaxPoolPreparedStatementPerConnectionSize());
}
if (dataSourceProperties.getConnectionProperties()!=null) {
datasource.setConnectionProperties(dataSourceProperties.getConnectionProperties());
}
if (dataSourceProperties.getUseGlobalDataSourceStat()!=null) {
datasource.setUseGlobalDataSourceStat(dataSourceProperties.getUseGlobalDataSourceStat());
}
try {
datasource.setFilters(dataSourceProperties.getFilters());
} catch (SQLException e) {
logger.error("dataSource configuration initialization filter", e);
}
return datasource;
}
그 중에서 DataSourceProperties 류 는 application. properties 를 주입 한 spring. datasource 의 매개 변수 입 니 다.
2.5, application. properties 에 두 번 째 datasource 설정 을 추가 합 니 다.
second.datasource.url=jdbc:oracle:thin:@//127.0.0.1:1521/testdb2
second.datasource.username=test2
second.datasource.password=test2
2.6 사용 방법
//
City city = cityService.getCityById(id,null);
//
DatabaseContextHolder.setDatabaseName(MyBatisConfiguration.DATASOURCE_SECOND_KEY);
city = cityService.getCityById(id,null);
DatabaseContextHolder.clear();
위 와 같이 우 리 는 두 개의 라 이브 러 리 에 city 표를 만 들 고 모두 city Id = 1 의 기록 을 설정 합 니 다. 첫 번 째 라 이브 러 리, city Name = 심 천, 두 번 째 라 이브 러 리, city Name = 로스앤젤레스.위의 두 번 의 요청 을 통 해 돌아 온 city Name 결 과 는 예상 한 대로 데이터 원본 이 정상적으로 전환 되 었 음 을 설명 합 니 다.메모: DataSource 를 전환 할 때마다 DatabaseContextHolder. clear () 를 사용 하 십시오.방법 은 스 레 드 변 수 를 비 웁 니 다.
후속
1. 위 에 적 힌 것 은 applicationContext 에 여러 개의 DataSource. class 의 bean 이 있 으 면 시작 할 때 mapper 타 임 스 를 생 성 하 는 오류 가 발생 할 수 있 습 니 다.그 중 하나 인 DataSource 의 bean 에 @ Primary 주 해 를 추가 하면 2, 이상 dataSource () 방법 을 덮어 쓰 고 돌아 오 는 DataSource 의 인 스 턴 스 는 DynamicDataSource 의 인 스 턴 스 로 전체 프로젝트 의 업무 가 실 효 될 수 있 으 므 로 시스템 에 업무 가 필요 한 곳 이 있 으 면 다 중 데이터 원본 설정 을 신 중 히 사용 해 야 합 니 다.다 중 데이터 소스 가 비교적 적합 한 장면 은 데이터 분석 이 고 대부분 은 논 리 를 조회 하고 서로 다른 라 이브 러 리 의 데 이 터 를 통합 시킨다.3. 상기 방식 은 SqlSessionTemplate 조회 만 지원 하지만, 이러한 조 회 는 반드시 mapper 가 있 는 sqlId 에 대응 해 야 합 니 다.사용자 정의 sql 을 사용 하여 조회 할 필요 가 있 으 면 대부분 jdbcTemplate 를 사용 합 니 다. 그러나 이때 jdbcTemplate 에서 사용 하 는 dataSource 는 동적 데이터 원본 이 아니 기 때문에 jdbcTemplate 를 사용 하면 데이터 원본 을 전환 하 는 효 과 를 낼 수 없습니다.이 를 위해 mybatis 의 가장 간단 한 사용자 정의 SQL 문장 을 참고 할 수 있 습 니 다. 원 리 는 마 퍼 를 새로 만 드 는 것 입 니 다.
List
parameterType 이 String 이면 매개 변수 이름 을 써 야 합 니 다parameter, \ # {sqlStr} 을 사용 할 수 없습니다. 그렇지 않 으 면 sql 주입 오류 가 발생 할 수 있 습 니 다.
참고 자료 제8 장 springboot + mybatis + 다 중 데이터 원본 Spring Boot Druid 데이터 원본 설정
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.