개발/java

JPA 데이터 소스 여러개 적용하기

코딩하는꽃개 2023. 5. 18. 13:01
반응형

JPA에 데이터 소스를 여러개 적용하여 DB를 2개 이상 연결할 수 있습니다.

 

우선 설정 클래스 정의가 필요 합니다.

메인으로 사용하는 Primay 데이터 소스를 설정 한 후 그 외 데이터 소스들을 지정해 주도록 합시다.

@Primay 어노테이션으로 메인 설정이 가능합니다.

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
    entityManagerFactoryRef = "firstEntityManagerFactory",
    transactionManagerRef = "firstTransactionManager",
    basePackages = { "com.hanainu.test.repository.first" }
)
public class FirstDataSourceConfig {
    @Autowired
    Environment env;

    @Primary
    @Bean
    @ConfigurationProperties("spring.first-datasource")
    public DataSourceProperties firstDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Primary
    @Bean
    @ConfigurationProperties("spring.first-datasource")
    public HikariDataSource firstDataSource(@Qualifier("firstDataSourceProperties") DataSourceProperties properties) {
        return properties.initializeDataSourceBuilder().type(HikariDataSource.class)
            .build();
    }

    @Primary
    @Bean
    public LocalContainerEntityManagerFactoryBean marketEntityManagerFactory(EntityManagerFactoryBuilder builder,
                                                                              @Qualifier("firstDataSource") DataSource firstDataSource) {
        return builder
            .dataSource(firstDataSource)
            .packages("com.hanainu.test.data.entity.first")
            .persistenceUnit("firstEntityManager")
            .build();
    }

    @Primary
    @Bean
    public PlatformTransactionManager firstTransactionManager(@Qualifier("firstEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }

    @Primary
    @Bean
    public JPAQueryFactory firstQueryFactory(@Qualifier("firstEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
        return new JPAQueryFactory(entityManagerFactory.createEntityManager());
    }
}

 

@Repository
public abstract class FirstQuerydslRepositorySupport extends QuerydslRepositorySupport {
    public FirstQuerydslRepositorySupport(Class<?> domainClass) {
        super(domainClass);
    }

    @Primary
    @Override
    @PersistenceContext(unitName = "firstEntityManager")
    public void setEntityManager(EntityManager entityManager) {
        super.setEntityManager(entityManager);
    }
}

 

 

 

 

이후 추가로 연결할 데이터 소스를 설정해 줍니다.

 

 

 

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
    entityManagerFactoryRef = "secondEntityManagerFactory",
    transactionManagerRef = "secondTransactionManager",
    basePackages = { "com.hanainu.test.repository.second" }
)
public class SecondDataSourceConfig {
    @Autowired
    Environment env;


    @Bean
    @ConfigurationProperties("spring.second-datasource")
    public DataSourceProperties secondDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @ConfigurationProperties("spring.second-datasource")
    public HikariDataSource secondDataSource(@Qualifier("secondDataSourceProperties") DataSourceProperties properties) {
        return properties.initializeDataSourceBuilder().type(HikariDataSource.class)
            .build();
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean secondEntityManagerFactory(EntityManagerFactoryBuilder builder,
                                                                              @Qualifier("secondSource") DataSource secondDataSource) {
        return builder
            .dataSource(secondDataSource)
            .packages("com.hanainu.test.data.entity.second")
            .persistenceUnit("secondEntityManager")
            .build();
    }

    @Bean
    public PlatformTransactionManager secondTransactionManager(@Qualifier("secondEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }

    @Bean
    public JPAQueryFactory secondQueryFactory(@Qualifier("secondEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
        return new JPAQueryFactory(entityManagerFactory.createEntityManager());
    }
}

 

 

@Repository
public abstract class SecondQuerydslRepositorySupport extends QuerydslRepositorySupport {
    public SecondQuerydslRepositorySupport(Class<?> domainClass) {
        super(domainClass);
    }

    @Override
    @PersistenceContext(unitName = "secibdEntityManager")
    public void setEntityManager(EntityManager entityManager) {
        super.setEntityManager(entityManager);
    }
}

 

클래스 설정이 완료 되었으면, 해당 설정에서 불러올 데이터 소스 정보를 application.yml 안에 작성합니다.

 

spring:
  first-datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: 
    password: 
    url:
    hikari:
      max-lifetime: 300000
      maximum-pool-size: 1
  second-datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: 
    password: 
    url:
    hikari:
      max-lifetime: 300000
      maximum-pool-size: 1

 

 

설정이 완료된 후는 아래와 같이 레포지토리 구현체를 정의해 주면 여러개의 데이터소스에 접근할 수 있습니다.

@Primay로 정의된 데이터소스의 레포지토리를 정의할 경우 queryFactory를 별도로 지정하지 않아도 사용 가능합니다.

@Repository
public class FirstRepositoryImpl extends FirstQuerydslRepositorySupport implements FirstRepositoryDsl {
    private final JPAQueryFactory queryFactory;

    @PersistenceContext
    private EntityManager em;

    public FirstRepositoryImpl(JPAQueryFactory queryFactory) {
        super(FirstSampleEntity.class);
        this.queryFactory = queryFactory;
    }
    
    // 레포지토리 구현
    ...(중략)
}

 

추가로 정의한 데이터 소스를 이용하는 레퍼지토리의 경우 .queryFactory를 지정해줘야 연결이 됩니다.

지정하지 않을시 @Primay로 지정한 데이터 소스로 연결되어 "~ is not mapped" 라는 에러가 발생합니다.

 

@Repository
public class SecondRepositoryImpl extends SecondQuerydslRepositorySupport implements SecondRepositoryDsl {
    private final JPAQueryFactory queryFactory;

    @PersistenceContext(unitName = "SecondEntityManager")
    private EntityManager em;

    public MarketUploadRepositoryImpl(@Qualifier("SecondQueryFactory") JPAQueryFactory queryFactory) {
        super(SecondSampleEntity.class);
        this.queryFactory = queryFactory;
    }

    // 레포지토리 구현
    ...(중략)
}

 

레포지토리 만드는 방법에 대한 제사한 내용은 아래의 링크에서 확인해 보세요

 

QueryDsl SpringBoot JPA 레포지토리 만들기

querydsl은 JPA 쿼리를 동적 코드로써 작성할 수 있도록 도와주는 ORM 프레임워크입니다. JPA에서 기본적으로 JPQL을 사용하여 레포지토리를 정의할 수 있습니다. @Repository public class ProductRepositoryImpl im

hanainu.tistory.com

 

반응형