JPA DataSource 이중화

최준호·2022년 1월 28일
0

업무

목록 보기
8/31

Batch 프로젝트를 설정하면서 JDBC가 아닌 JPA로 변경할 때 DataSource가 여러개를 분리하여 적용할 수 있도록 설정하는 부분이 필요했다.

Config 파일 설정

@Configuration
@EnableJpaRepositories(entityManagerFactoryRef = "batchEntityManager", transactionManagerRef = "batchTransactionManager", basePackages = "com.codeblock.batch.repository.batch")
public class BatchDbConfig {

    @Autowired
    private Environment env;

    @Primary
    @Bean(name = "batchDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.batch.hikari")
    public DataSource dataSourceBatch(){
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }

    @Primary
    @Bean
    public LocalContainerEntityManagerFactoryBean batchEntityManager(){
        LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean();
        HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();

        bean.setDataSource(dataSourceBatch());
        bean.setJpaPropertyMap(createProperties());
        bean.setPackagesToScan(new String[] {"com.codeblock.batch.domain.entity"});
        bean.setJpaVendorAdapter(hibernateJpaVendorAdapter);
        return bean;
    }

    private Map<String, ?> createProperties() {
        Map<String, Object> map = new HashMap<>();
        map.put("hibernate.show_sql", env.getProperty("spring.datasource.batch.hikari.jpa.show-sql"));
        map.put("hibernate.hbm2ddl.auto", env.getProperty("spring.datasource.batch.hikari.jpa.ddl-auto"));
        return map;
    }

    @Primary
    @Bean
    public PlatformTransactionManager batchTransactionManager(){
        JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
        jpaTransactionManager.setEntityManagerFactory(batchEntityManager().getObject());
        return jpaTransactionManager;
    }
}

먼저 batch가 사용할 data source를 @Primary를 통해 선언해둔다.

@Configuration
@EnableJpaRepositories(entityManagerFactoryRef = "creshEntityManager", transactionManagerRef = "creshTransactionManager", basePackages ="reposiotry 패키지 경로")
public class CreshDbConfig {

    @Autowired
    private Environment env;

    @Bean(name = "creshDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.cresh.hikari")
    public DataSource dataSourceCresh(){
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean creshEntityManager(){
        LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean();
        HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();

        bean.setDataSource(dataSourceCresh());
        bean.setJpaPropertyMap(createProperties());
        bean.setPackagesToScan(new String[] {"entity 패키지 경로"});
        bean.setJpaVendorAdapter(hibernateJpaVendorAdapter);
        return bean;
    }

    private Map<String, ?> createProperties() {
        Map<String, Object> map = new HashMap<>();
        map.put("hibernate.format_sql", env.getProperty("spring.datasource.cresh.hikari.jpa.show-sql"));
        //map.put("hibernate.show-sql", env.getProperty("spring.datasource.cresh.hikari.jpa.show-sql"));
        map.put("hibernate.hbm2ddl.auto", env.getProperty("spring.datasource.cresh.hikari.jpa.ddl-auto"));
        return map;
    }

    @Bean
    public PlatformTransactionManager creshTransactionManager(){
        JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
        jpaTransactionManager.setEntityManagerFactory(creshEntityManager().getObject());
        return jpaTransactionManager;
    }
}

그 후 service db에 붙을 data source도 정의해준다.

여기서 중요한 부분은 basePackagesLocalContainerEntityManagerFactoryBean의 method 명 or bean name이 중요하다. basePackages로 선언한 repository package 경로인데 해당 경로를 com.example.패키지로 적어줘야한다.

다음으로는 LocalContainerEntityManagerFactoryBean의 entity 패키지 경로와 bean으로 등록되는 이름이다. entity의 패키지 경로에 맞게 생성된 entity들을 갖고 db와 작업을 진행하기 때문에 정확하게 적어줘야한다. 또한 bean의 이름은 repository에서 EntityManager를 상속시킬 때 중요하다.

Repository 설정

@Repository
public class TestRepository {
    @PersistenceContext(unitName = "creshEntityManager")
    private EntityManager em;

    public List<Test> findAll(){
        return em.createQuery("select t from Test t", Test.class).getResultList();
    }
}

repository는 다음과 같이 EntityManager를 선언해주는 것은 동일한데 unitName이라는 옵션을 사용한다. 이 옵션에 맞게 bean 이름이 등록되어 있어야 자동으로 상속시킬 수 있다.

profile
코딩을 깔끔하게 하고 싶어하는 초보 개발자 (편하게 글을 쓰기위해 반말체를 사용하고 있습니다! 양해 부탁드려요!) 현재 KakaoVX 근무중입니다!

0개의 댓글