ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • spring boot jpa Multiple datasource
    카테고리 없음 2023. 4. 20. 09:52
    스프링 부트의 여러개 데이터 소스를 써야 한다면 설정을 조금 해줘야한다. 회사에서 할때는 잘 안됐는데 집에서 한방에 됐다.ㅋㅋㅋㅋ 문제가 뭔지는 담주에 회사 가서 다시 천천히 살펴 봐야겠다. 원래 있던 소스에서 변경을 할라고 해서 뭔가 꼬였나. 아무튼 일단 한번 찬찬히 살펴보자
    spring:
      jpa:
        show-sql: true
        generate-ddl: true
        properties:
          hibernate:
            ddl-auto: validate
    user:
      datasource:
        url: jdbc:h2:tcp://localhost/~/user
        username: sa
        password:
        driverClassName: org.h2.Driver
    
    customer:
      datasource:
        url: jdbc:h2:tcp://localhost/~/customer
        username: sa
        password:
        driverClassName: org.h2.Driver
    
    application.yml 파일이다. 두개의 데이터 소스가 필요한 만큼 두개의 데이터소소를 입력하여 준다. 키들은 자신이 정하면 된다. 여기서는 user와 customer로 설정 하였다. 테스트를 위해 로컬에 있는 h2 디비를 사용했다. 일반적인 JPA와 중요치 않은 소스들은 github 에서 참고 하길 바란다. customer 대한 데이터 소스 셋팅을 먼저 알아보겠다.
    @Configuration
    @EnableTransactionManagement
    @EnableJpaRepositories(
      basePackages = {"me.wonwoo.customer.repository"})
    public class CustomerDataSourceConfig {
    
      @Primary
      @Bean(name = "dataSource")
      @ConfigurationProperties(prefix = "customer.datasource")
      public DataSource dataSource() {
        return DataSourceBuilder.create().build();
      }
    
      @Primary
      @Bean(name = "entityManagerFactory")
      public LocalContainerEntityManagerFactoryBean entityManagerFactory(
        EntityManagerFactoryBuilder builder, @Qualifier("dataSource") DataSource dataSource) {
        return builder
          .dataSource(dataSource)
          .packages("me.wonwoo.customer.domain")
          .persistenceUnit("customer")
          .build();
      }
    
      @Primary
      @Bean(name = "transactionManager")
      public PlatformTransactionManager transactionManager(
        @Qualifier("entityManagerFactory") EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
      }
    }
    
    아주 간편하다. @EnableJpaRepositories basePackages에는 스캔대상이 될 레파지토리의 패키지명이다. entityManagerFactory 빈의 packages는 스캔대상이 될 도메인 (엔티티) 패키지명이다. @Qualifier을 잘 지정해주자. 아니면 잘 동작하지 않는다. 다음으로는 user에 대한 데이터소스 이다.
    @Configuration
    @EnableTransactionManagement
    @EnableJpaRepositories(
      entityManagerFactoryRef = "userEntityManagerFactory",
      transactionManagerRef = "userTransactionManager",
      basePackages = {"me.wonwoo.user.repository"})
    public class UserDataSourceConfig {
    
      @Bean(name = "userDataSource")
      @ConfigurationProperties(prefix = "user.datasource")
      public DataSource userDataSource() {
        return DataSourceBuilder.create().build();
      }
    
      @Bean(name = "userEntityManagerFactory")
      public LocalContainerEntityManagerFactoryBean userEntityManagerFactory(
        EntityManagerFactoryBuilder builder, @Qualifier("userDataSource") DataSource userDataSource) {
        return builder
          .dataSource(userDataSource)
          .packages("me.wonwoo.user.domain")
          .persistenceUnit("user")
          .build();
      }
    
      @Bean(name = "userTransactionManager")
      public PlatformTransactionManager userTransactionManager(
        @Qualifier("userEntityManagerFactory") EntityManagerFactory userEntityManagerFactory) {
        return new JpaTransactionManager(userEntityManagerFactory);
      }
    }
    
    위와 비슷하지만 빈명을 다르게 등록하는게 핵심이다. 만약 빈명이 같을 경우에는 에러를 내뱉는다. 여기서도 마찬가지로 @Qualifier 을 잘 지정해주자! 테스트 데이터를 넣은 후에 테스트를 해보자.
    @Test
    public void userTest() {
        userRepository.findAll()
            .stream()
            .map(i -> i.toString())
            .forEach(log::info);
    }
    
    @Test
    public void custoemrTest(){
        customerRepository.findAll()
            .stream()
            .map(i -> i.toString())
            .forEach(log::info);
    }
    
    아주 잘 동작한다. user는 user 데이터베이스에 customer는 cusomter 데이터베이스에서 잘 가져온다. 얼른 회사가서 해봐야겠다. 뭔가 놓친게 분명해! 트랜잭션 처리도 아마 잘 되겠지? 필자는 select만 할거라 트랜잭션이 굳이 필요 없긴한데... 만약 안되면 다시 알아봐야겠다. 4일동안 쉬니까 오늘은 좀 쉬어야 겠다.

    댓글

Designed by Tistory.