DB 를 수동으로 설정해야할 경우
- DB를 하나만 사용하면 굳이 수동으로 설저할 필요가 없다. 하지만 아래와 같은 경우엔 DB를 수동으로 설정할 필요가 있다.
- 자바 코드로 DataSource, TransactionManager 를 수동 세팅해야 하는 경우
- configuration properties 로 커버되지 않는 세밀한 옵션을 줄 때
- 다중 DataSource 를 사용할 때
DB 세팅 요소
- 먼저 DataSource 를 세팅한다. -> DB 설정
- 그 다음 DataSource 를 바탕으로 EntityManagerFactory 를 세팅한다. -> PA 엔티티 관리
- 그 다음 EntityManagerFactory를 바탕으로 LocalContainerEntityManagerFactoryBean를 세팅한다. -> 트랜잭션 관리
설정 코드
@EnableJpaAuditing
public class JpaConfig {
@ConfigurationProperties("spring.datasource")
@Bean
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
@Bean
public DataSource dataSource2() {
return DataSourceBuilder.create().build();
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("com.hyunwook.servicedesk");
factory.setDataSource(dataSource());
return factory;
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory2() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("com.hyunwook.servicedesk");
factory.setDataSource(dataSource());
return factory;
}
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory);
return txManager;
}
@Bean
public PlatformTransactionManager transactionManager2(EntityManagerFactory entityManagerFactory2) {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory2);
return txManager;
}
@Bean
public ChainedTransactionManager chainedTransactionManager(
PlatformTransactionManager transactionManager,
PlatformTransactionManager transactionManager2
) {
return new ChainedTransactionManager(transactionManager, transactionManager2);
}
}
- 위와 같이 DataSource 가 2개일 때, EntityManagerFactory 와 LocalContainerEntityManagerFactoryBean 를 따로 구성해준다.
- LocalContainerEntityManagerFactoryBean 의 경우, 추가적인 예외 처리 기능 때문에, 인터페이스 말고 구현체를 직접 빈으로 등록한다.
- 마지막으로, ChainedTransactionManager 를 통해서 여러 개의 트랜잭션 매니저를 묶는다.
- 여기서 순서가 중요한데, 로직상 중요한 트랜잭션을 뒤에 위치시켜야 한다.
- 또한, spring boot 2.5 버전부터 Deprecated 되었기 때문에, 대안으로 TransactionSyncronization 를 사용해서 구현해야 된다.
REFERENCES