[Querydsl] 멀티 DB (Multi DB) 연결, 설정하기

1. application.yml에 데이터소스 추가하기

Spring Boot 프로젝트에서 두 개의 데이터베이스를 사용하기 위해 application.yml 파일에 각각의 데이터소스를 정의해줍니다.

spring:
  datasource:
    driverClassName: org.mariadb.jdbc.Driver
    url: jdbc:mariadb://localhost:3306/{DB명}
    username: {DB user}
    password: {DB password}

  second-datasource:
    driverClassName: org.mariadb.jdbc.Driver
    url: jdbc:mariadb://localhost:3306/{DB명}
    username: {DB user}
    password: {DB password}

2. 데이터소스 설정

1) 첫 번째 데이터베이스 설정

기본 데이터베이스 설정을 위해 @Primary 어노테이션을 사용해야 하며, 관련된 설정을 아래와 같이 구성합니다.

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
    basePackages = ["패키지1", "패기지2"],
    entityManagerFactoryRef = "entityManagerFactory",
    transactionManagerRef = "transactionManager"
)
class DatasourceConfig {

    @Bean
    @Primary
    @ConfigurationProperties("spring.datasource")
    fun datasourceProperties(): DataSourceProperties {
        return DataSourceProperties()
    }

    @Bean
    @Primary
    @ConfigurationProperties("spring.datasource.configuration")
    fun primaryDatasource(): DataSource {
        return datasourceProperties()
            .initializeDataSourceBuilder()
            .type(HikariDataSource::class.java)
            .build()
    }

    @Bean(name = ["entityManagerFactory"])
    @Primary
    fun entityManagerFactory(builder: EntityManagerFactoryBuilder): LocalContainerEntityManagerFactoryBean {
        val dataSource: DataSource = primaryDatasource()
        return builder
            .dataSource(dataSource)
            .packages("패키지1", "패기지2")
            .persistenceUnit("entityManager")
            .build()
    }

    @Bean(name = ["transactionManager"])
    @Primary
    fun transactionManager(
        @Qualifier("entityManagerFactory") factory: LocalContainerEntityManagerFactoryBean
    ): PlatformTransactionManager {
        return JpaTransactionManager(factory.getObject()!!)
    }
}

첫 번째 데이터소스의 빈에는 @Primary를 꼭 붙여야 빈 충돌 없이 제대로 주입됩니다.

처음에는 entityManagerFactoryReftransactionManagerRef에 접두어를 붙여 사용했지만, 아래와 같은 에러가 발생했습니다:

required a bean named 'entityManagerFactory' that could not be found.

이후 기본 이름으로 설정하면서 문제를 해결했습니다.

2) 두 번째 데이터베이스 설정

보조 DB는 별도의 설정 클래스를 만들어 관리하며, EntityManagerFactoryTransactionManager 이름도 달리 지정합니다.

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
    basePackages = ["패키지"],
    entityManagerFactoryRef = "secondEntityManagerFactory",
    transactionManagerRef = "secondTransactionManager"
)
class SecondDatasourceConfig {

    @Bean
    @ConfigurationProperties("spring.second-datasource")
    fun secondDatasourceProperties(): DataSourceProperties {
        return DataSourceProperties()
    }

    @Bean
    @ConfigurationProperties("spring.second-datasource.configuration")
    fun secondDatasource(): DataSource {
        return secondDatasourceProperties()
            .initializeDataSourceBuilder()
            .type(HikariDataSource::class.java)
            .build()
    }

    @Bean(name = ["secondEntityManagerFactory"])
    fun secondEntityManagerFactory(builder: EntityManagerFactoryBuilder): LocalContainerEntityManagerFactoryBean {
        val dataSource = secondDatasource()
        return builder
            .dataSource(dataSource)
            .packages("패키지")
            .persistenceUnit("secondEntityManager")
            .build()
    }

    @Bean(name = ["secondTransactionManager"])
    fun secondTransactionManager(
        @Qualifier("secondEntityManagerFactory") factory: LocalContainerEntityManagerFactoryBean
    ): PlatformTransactionManager {
        return JpaTransactionManager(factory.getObject()!!)
    }
}

3. Bean 등록 및 QueryDsl 설정

QueryDsl을 사용하기 위해 EntityManager를 주입받고, 각각에 대한 JPAQueryFactory 빈을 등록해줍니다.

@Configuration
@EnableConfigurationProperties
class AppConfig(
    @PersistenceContext(unitName = "entityManager")
    val entityManager: EntityManager,
    @PersistenceContext(unitName = "secondEntityManager")
    val secondEntityManager: EntityManager
) {

    @Primary
    @Bean
    fun queryFactory(): JPAQueryFactory {
        return JPAQueryFactory(entityManager)
    }

    @Bean
    @Qualifier("secondQueryFactory")
    fun secondQueryFactory(): JPAQueryFactory {
        return JPAQueryFactory(secondEntityManager)
    }
}

@Primary가 적용된 기본 JPAQueryFactory는 별도 지정 없이 사용할 수 있으며, 두 번째 DB에 대한 QueryDsl은 @Qualifier("secondQueryFactory")를 통해 명시적으로 주입하여 사용합니다.

댓글

이 블로그의 인기 게시물

[Python] 리스트에서 특정 값 , 원소 위치, 원소 개수 찾기

jar 파일 빌드 시 테스트 파일 제외

[PHP] AWS S3 sdk 파일 업로드 하기