다중 DataSource 구성
하나의 애플리케이션에서 여러 DB(메인 DB, 이메일 DB, 외부 연동 DB 등)에 독립적으로 접근해야 할 때 DataSource별 @Configuration 클래스를 분리하여 등록한다.
구성 원칙
| 규칙 | 설명 |
|---|---|
| DataSource별 Config 클래스 분리 | DataBaseHomeConfig, DataBaseEmailConfig 등 |
메인 DataSource에 @Primary 적용 | Spring이 기본으로 주입할 DataSource 지정 |
@Qualifier로 비주요 DataSource 지정 | 명시적으로 Bean 이름 지정 |
| SqlSessionFactory 분리 | DataSource마다 별도 SqlSessionFactory 등록 |
| Mapper 패키지 분리 | DataSource별 Mapper XML 경로 분리 |
메인 DataSource 설정 예시
@Configuration
@MapperScan(
basePackages = "com.{회사명}.{프로젝트명}.home.mapper",
sqlSessionFactoryRef = "homeSqlSessionFactory"
)
public class DataBaseHomeConfig {
@Primary
@Bean(name = "homeDataSource")
@ConfigurationProperties(prefix = "spring.datasource.home")
public DataSource homeDataSource() {
return DataSourceBuilder.create().build();
}
@Primary
@Bean(name = "homeSqlSessionFactory")
public SqlSessionFactory homeSqlSessionFactory(
@Qualifier("homeDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
factory.setDataSource(dataSource);
factory.setConfigLocation(
new ClassPathResource("mybatis/mybatis-config.xml"));
factory.setMapperLocations(
new PathMatchingResourcePatternResolver()
.getResources("classpath:mybatis/home/**/mapper/*.xml"));
return factory.getObject();
}
@Primary
@Bean(name = "homeTransactionManager")
public DataSourceTransactionManager homeTransactionManager(
@Qualifier("homeDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
보조 DataSource 설정 예시
@Configuration
@MapperScan(
basePackages = "com.{회사명}.{프로젝트명}.email.mapper",
sqlSessionFactoryRef = "emailSqlSessionFactory"
)
public class DataBaseEmailConfig {
@Bean(name = "emailDataSource")
@ConfigurationProperties(prefix = "spring.datasource.email")
public DataSource emailDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "emailSqlSessionFactory")
public SqlSessionFactory emailSqlSessionFactory(
@Qualifier("emailDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
factory.setDataSource(dataSource);
factory.setMapperLocations(
new PathMatchingResourcePatternResolver()
.getResources("classpath:mybatis/email/**/mapper/*.xml"));
return factory.getObject();
}
@Bean(name = "emailTransactionManager")
public DataSourceTransactionManager emailTransactionManager(
@Qualifier("emailDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
application.yml 설정
spring:
datasource:
home:
driver-class-name: oracle.jdbc.OracleDriver
url: ${DB_HOME_URL}
username: ${DB_HOME_USERNAME}
password: ${DB_HOME_PASSWORD}
email:
driver-class-name: oracle.jdbc.OracleDriver
url: ${DB_EMAIL_URL}
username: ${DB_EMAIL_USERNAME}
password: ${DB_EMAIL_PASSWORD}
@Transactional 사용 시 주의
트랜잭션 매니저가 여러 개이므로 @Transactional에 명시적으로 지정한다.
// 메인 DB (@Primary이므로 생략 가능)
@Transactional(transactionManager = "homeTransactionManager")
public void saveOrder(OrderVo vo) { ... }
// 보조 DB (반드시 명시)
@Transactional(transactionManager = "emailTransactionManager")
public void sendEmail(EmailVo vo) { ... }
디렉터리 구조
src/main/resources/mybatis/
├── mybatis-config.xml # 공통 MyBatis 설정
├── home/
│ └── mapper/
│ └── UserMapper.xml
└── email/
└── mapper/
└── EmailMapper.xml
체크리스트
- [ ] DataSource별
@Configuration클래스 분리 - [ ] 메인 DataSource에
@Primary적용 - [ ]
@MapperScan의sqlSessionFactoryRef명시 - [ ] Mapper XML 경로를 DataSource별로 분리
- [ ]
@Transactional에transactionManager명시 (비주요 DS) - [ ]
application.yml에 DataSource별 prefix 분리