Batch 프로젝트를 설정하면서 JDBC가 아닌 JPA로 변경할 때 DataSource가 여러개를 분리하여 적용할 수 있도록 설정하는 부분이 필요했다.
@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도 정의해준다.
여기서 중요한 부분은 basePackages
와 LocalContainerEntityManagerFactoryBean
의 method 명 or bean name이 중요하다. basePackages로 선언한 repository package 경로인데 해당 경로를 com.example.패키지
로 적어줘야한다.
다음으로는 LocalContainerEntityManagerFactoryBean
의 entity 패키지 경로와 bean으로 등록되는 이름이다. entity의 패키지 경로에 맞게 생성된 entity들을 갖고 db와 작업을 진행하기 때문에 정확하게 적어줘야한다. 또한 bean의 이름은 repository에서 EntityManager를 상속시킬 때 중요하다.
@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 이름이 등록되어 있어야 자동으로 상속시킬 수 있다.