Spring Boot 애플리케이션에서 여러 데이터베이스를 사용하고 각각의 트랜잭션을 제어하는 방법을 설명합니다.
애플리케이션 시작 지점에 @EnableTransactionManagement 어노테이션을 추가하여 트랜잭션 관리를 활성화합니다.
package com.example.multidb;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
@ComponentScan(basePackages={"com.example.multidb"})
@EnableCaching
@EnableTransactionManagement
public class MultiDatabaseApplication {
public static void main(String[] args) {
SpringApplication.run(MultiDatabaseApplication.class, args);
}
}
application.properties 파일에 두 개의 데이터 소스 설정을 구성합니다.
# 첫 번째 데이터베이스 설정
spring.datasource.primary.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.primary.url=jdbc:mysql://192.168.18.221:3306/main_db?characterEncoding=utf8&useSSL=true
spring.datasource.primary.username=admin
spring.datasource.primary.password=admin123
# 두 번째 데이터베이스 설정
spring.datasource.secondary.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.secondary.url=jdbc:mysql://192.168.18.221:3306/secondary_db?characterEncoding=utf8&useSSL=true
spring.datasource.secondary.username=admin
spring.datasource.secondary.password=admin123
Java 기반 설정 클래스를 생성하여 데이터 소스와 템플릿을 정의합니다. @Configuration 어노테이션을 적용하고 필요한 빈들을 구성합니다.
package com.example.multidb.config;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
@Configuration
public class DatabaseConfiguration {
@Bean(name = "primaryDataSource")
@Qualifier("primaryDataSource")
@Primary
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource mainDataSource() {
System.out.println("=== Primary DataSource 초기화 ===");
return DataSourceBuilder.create().build();
}
@Bean(name = "secondaryDataSource")
@Qualifier("secondaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public DataSource additionalDataSource() {
System.out.println("=== Secondary DataSource 초기화 ===");
return DataSourceBuilder.create().build();
}
@Bean(name = "primaryJdbcTemplate")
public JdbcTemplate mainJdbcTemplate(@Qualifier("primaryDataSource") DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Bean(name = "secondaryJdbcTemplate")
public JdbcTemplate additionalJdbcTemplate(@Qualifier("secondaryDataSource") DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
// 트랜잭션 매니저 설정
@Bean
public PlatformTransactionManager primaryTxManager(@Qualifier("primaryDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean
public PlatformTransactionManager secondaryTxManager(@Qualifier("secondaryDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
서비스 계층에서 특정 데이터 소스의 트랜잭션을 사용하려면 다음과 같이 @Transactional 어노테이션을 적용합니다.
@Transactional(value = "secondaryTxManager", readOnly = true)
public Entity findById(Long id) {
return repository.findById(id);
}
@Transactional(value = "secondaryTxManager")
public void updateRecord(String value) {
repository.update(value);
int result = 10 / 0; // 예외 발생 테스트
}
특정 데이터 소스의 JdbcTemplate이나 DataSource를 주입받고자 할 때는 @Qualifier 어노테이션을 사용합니다.
@Autowired
@Qualifier("secondaryJdbcTemplate")
private JdbcTemplate secondaryTemplate;
@Autowired
@Qualifier("secondaryDataSource")
private DataSource secondaryDs;
@Autowired
@Qualifier("primaryJdbcTemplate")
private JdbcTemplate primaryTemplate;
@Autowired
@Qualifier("primaryDataSource")
private DataSource primaryDs;