스프링부트 내에서 Database를 구성할 때 보통 application.yml에서 다음과 같이 작성한다.
spring:
datasource:
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://localhost:5432/dbname
platform: postgres
username: username
password: password
대부분의 작은 프로젝트에서는 이렇게 단일 DB로 구성되지만, 여러 개의 DB로 나누어 관리하거나 외부 DB를 참조해야 할 경우 다중 데이터베이스 구성이 필요하다.
나는 PostgreSQL 로컬 DB 하나와, 외부에서 참조할 PostgreSQL, MySQL DB 하나씩 연동이 필요한 상황이었다.
먼저 각각의 구성 정보를 db1, db2, db3과 같이 나누어 담아준다.
application.yml
# 다중 Database 구성
datasource:
db1:
jdbcUrl: jdbc:postgresql://localhost:5432/dbname
username: username
password: password
driverClassName: org.postgresql.Driver
db2:
jdbcUrl: jdbc:postgresql://localhost:5432/dbname
username: username
password: password
driverClassName: org.postgresql.Driver
db3:
dialect: org.hibernate.dialect.MySQLDialect
jdbcUrl: jdbc:mysql://localhost:5432/dbname
username: username
password: password
driverClassName: com.mysql.jdbc.Driver
단일 DB 구성에서는 yaml파일을 작성하면 프로젝트 내에서 자동으로 연동되지만, 다중 DB는 이 yaml파일 내의 정보를 이용해서 별도로 Config파일을 구성해주어야 한다.
Db1Config
@Configuration
@EnableJpaRepositories(
basePackages = "com.example.test.domain",
entityManagerFactoryRef = "db1EntityManagerFactory",
transactionManagerRef = "db1TransactionManager"
)
public class Db1Config {
@Primary
@Bean(name = "db1DataSource")
@ConfigurationProperties(prefix = "spring.datasource.db1")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
@Primary
@Bean(name = "db1EntityManagerFactory")
public LocalContainerEntityManagerFactoryBean
entityManagerFactory(EntityManagerFactoryBuilder builder,
@Qualifier("db1DataSource") DataSource dataSource) {
return builder
.dataSource(dataSource)
.packages("com.example.test.domain")
.persistenceUnit("db1")
.build();
}
@Primary
@Bean(name = "db1TransactionManager")
public PlatformTransactionManager transactionManager(
@Qualifier("db1EntityManagerFactory") EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
@EnableJpaRepositories 내 basePackages에 이 Config가 적용될 패키지 레벨을 설정한다.
그 후 각각 EntityManagerFactory와 TransactionManager 설정을 Bean으로 주입해준 뒤, @EnableJpaRepositories 어노테이션 내에 매핑해준다.
@Primaery 여러 Datasource 중 우선으로 사용할 Config에 붙여준다.
@Qualifier 여러 Datasource가 Bean으로 주입될 때 충돌되지 않도록 별칭으로 지정해준다.
그렇기 때문에 특정 데이터베이스의 config 파일에 @Primaery 어노테이션을 붙여서 Bean을 생성해주고, 그 외에 데이터베이스 설정 파일에는 @Qualifier 어노테이션 같은 걸로 지칭을 해줘야 한다.
Db2Config, Db3Config도 마찬가지로 구성하면 된다. 단, @Primary 어노테이션은 반드시 주 DB 구성에만 포함시켜야 한다. 그렇지 않을 경우 충돌이 발생해서 아래와 같은 오류가 발생한다.
Parameter 0 of method entityManagerFactory in com.example.test.global.config.Db1Config required a bean of type 'org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder' that could not be found.