애플리케이션이 여러 데이터베이스에 접속하여 작업하려면
- application.yml에 각 데이터베이스에 대한 datasource 설정
- 각 datasource에 대한 매퍼 사용과 트랜잭션 Configuration 클래스 작성
- 애플리케이션의
*Application.java
에 설정 클래스 적용
한다.
application.yml
application.yml의 spring.datasource.hikari 항목 아래에 각 datasource에 대한 정보를 이름을 붙여 설정한다.
다음은 2개 datasource에 대한 정보를 각각 first, second라는 이름으로 설정한 예다.
spring:
datasource:
hikari:
first:
driver-class-name: ...
jdbc-url: ...
username: ...
password: ...
auto-commit: false
# 개발 환경에서만 활성화. 운영환경에서는 조정하거나 제거할 것
maximumPoolSize: 3
second:
driver-class-name: ...
jdbc-url: ...
username: ...
password: ...
auto-commit: false
# 개발 환경에서만 활성화. 운영환경에서는 조정하거나 제거할 것
maximumPoolSize: 3
Datasource / 트랜잭션 설정 클래스 작성
application.yml에 설정한 정보를 읽어 datasource에 대한 매퍼 사용과 트랜잭션을 관리하는 Bean들을 애플리케이션 컨텍스트에 등록하는 설정 클래스를 작성한다.
Datasource 설정 클래스
특정 datasource에 접근해 작업하는 매퍼는 특정 base package 아래의 패키지에 속해야 하고, 매퍼 xml 파일들의 경로도 특정 디렉토리 아래에 위치해야 한다.
Datasource 설정 클래스는
- application.yml에서 읽어야할 datasource 설정 지정
- sqlSession 이름 지정
- 매퍼의 base package
- 매퍼가 사용하는 xml 파일들의 클래스패스 상의 경로
등을 설정한다.
Datasource 설정 클래스는
- cokr.xit.foundation.boot.AbstractDatasource 또는
- cokr.xit.foundation.boot.DatasourceConfig
을 상속받아 작성한다.
DatasourceConfig 확장
DatasourceConfig는 디폴트 datasource 설정 클래스로, 애플리케이션 컨텍스트에 Bean들을 기본이름으로 등록할 경우 상속받는다.
다음은 first datasource 설정을 읽는 클래스를 DatasourceConfig를 상속받아 작성한 예다.
public class FirstDatasource extends DatasourceConfig {
@Override
@ConfigurationProperties(prefix = "spring.datasource.hikari.first") // application.yml에서 읽어야할 datasource 설정 이름
public DataSource dataSource() {
return super.dataSource();
}
@Override
protected String[] mapperLocationPatterns() {
return new String[] {
"classpath:sql/mapper/base/*.xml",
"classpath:sql/mapper/first/*.xml"
};
}
@Override
protected String mapperBasePackages() {
return "cokr.xit.base;cokr.xit.first"; // 여러 개일 경우 세미콜런이나 콤마로 구분
}
}
AbstractDatasource 확장
AbstractDatasource는 애플리케이션 컨텍스트에 Bean들을 기본과 다른 이름으로 등록할 경우 상속받는다.
다음은 second datasource 설정을 읽는 클래스를 AbstractDatasource를 상속받아 작성한 예다.
public static class SecondDatasource extends AbstractDatasource {
private static final String SQL_SESSION = "secondSession";
@Override
@Bean("secondDataSource") // Bean 이름 변경
@ConfigurationProperties(prefix = "spring.datasource.hikari.second") // application.yml에서 읽어야할 datasource 설정 이름
public DataSource dataSource() {
return super.dataSource();
}
@Override
@Bean(SQL_SESSION) // Bean 이름 변경
public SqlSessionFactoryBean sqlSession() {
return super.sqlSession();
}
@Override
protected String sqlSessionName() {
return SQL_SESSION;
}
@Override
protected String[] mapperLocationPatterns() {
return new String[] {
"classpath:sql/mapper/base/utility.xml",
"classpath:sql/mapper/second/**/*.xml"
};
}
@Override
protected String mapperBasePackages() {
return "cokr.xit.second"; // 여러 개일 경우 세미콜런이나 콤마로 구분
}
@Override
@Bean("secondMapperConfigurer") // Bean 이름 변경
public MapperConfigurer mapperConfigurer() {
return super.mapperConfigurer();
}
@Override
@Bean("secondIdProvider") // Bean 이름 변경
public VendorDatabaseIdProvider databaseIdProvider() {
return super.databaseIdProvider();
}
}
트랜잭션 설정 클래스
Datasource 설정 클래스는 트랜잭션 설정 클래스와 연동된다.
Bean의 이름을 기본값으로 사용하는 datasource 클래스, 즉 DatasourceConfig를 상속받아 작성한 클래스는 디폴트 트랜잭션 설정 클래스인 cokr.xit.foundation.boot.TransactionConfig와 연동된다.
AbstractDatasource를 상속받은 datasource 설정 클래스와 연동될 트랜잭션 설정 클래스는 cokr.xit.foundation.boot.AbstractTransaction을 상속받아 작성한다.
다음은 SecondDatasource 설정 클래스와 연동되는 트랜잭션 설정 클래스를 작성하는 예다.
@Configuration
@Aspect
@EnableTransactionManagement
@EnableAspectJAutoProxy(proxyTargetClass = true)
public static class SecondTransaction extends AbstractTransaction {
@Override
@Resource(name = "secondDataSource") // SecondDatasource가 제공하는 secondDataSource와 연동
public void setDataSource(DataSource dataSource) {
super.setDataSource(dataSource);
}
@Override
@Bean("secondTxManager") // Bean 이름 변경
public DataSourceTransactionManager txManager() {
return super.txManager();
}
@Override
@Bean("secondTxAdvice") // Bean 이름 변경
public TransactionInterceptor txAdvice() {
return super.txAdvice();
}
@Override
@Bean("secondTxAdvisor") // Bean 이름 변경
public Advisor txAdvisor() {
return super.txAdvisor();
}
}
설정 클래스 적용
애플리케이션이 여러 데이터베이스에 접속할 수 있도록 하려면 위와 같이 작성한 설정 클래스들을 적용해야 한다.
다음은 위에서 작성한 데이터베이스와 트랜잭션 설정 클래스들을 적용한 예다.
@ImportAutoConfiguration({
FirstDatasource.class,
SecondDatasource.class,
SecondTransaction.class
})
@ComponentScan(
excludeFilters = @ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
classes = {
DatasourceConfig.class
}
)
)
public class BusinessBootApplication extends XitBaseApplication {
...
}