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 이름이 등록되어 있어야 자동으로 상속시킬 수 있다.