@Scheduled 실행 시, Transaction처리
문제
BatchController로 직접 메소드를 호출하는 작업은 정상적으로 수행되나,
@scheduled
에 의해 실행되는 작업에 아래와 같은 에러가 발생한다.똑같은 메소드를 호출하도록 되어 있는 컨트롤러를 호출 시에는 정사 작동한다.
원인
- 트랜잭션 매니저가 @EnableTransactionManagement를 통해 DataSourceTransactionManager로 구성된 경우, 하이버네이트의
begin()
메소드가 AbstractTransactionImpl을 부르지 않는다고 한다. - 해결하기위해서는 트랜잭션 매니저를 JpaTransactionManager로 구현하여 사용해야한다.
해결
@Configuration
public class DatabaseConfig {
@Bean
@Primary
@ConfigurationProperties("spring.datasource")
public DataSourceProperties dataSourceProperties() {
return new DataSourceProperties();
}
@Bean(destroyMethod = "getLogWriter")
@Primary
public DataSource dataSource() {
return dataSourceProperties().initializeDataSourceBuilder().build();
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
localContainerEntityManagerFactoryBean.setPersistenceUnitName("defaultUnit");
localContainerEntityManagerFactoryBean.setDataSource(dataSource());
localContainerEntityManagerFactoryBean.setPackagesToScan("package");
localContainerEntityManagerFactoryBean.setPersistenceProvider(new HibernatePersistenceProvider());
return localContainerEntityManagerFactoryBean;
}
@Bean
@Primary
public PlatformTransactionManager jpaTransactionManager() {
JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
jpaTransactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
jpaTransactionManager.setJpaDialect(new HibernateJpaDialect());
return jpaTransactionManager;
}
}
JpaTransactionManager를 만들어서 빈으로 등록한다.
@Primary
어노테이션이 없는경우, 동일한 타입의 빈이 두개여서 에러발생실행 후, 테스트
- Controller 호춣하여 강제 실행,
@Scheduled
에 의한 실행 모두 정상으로 동작하는것을 확인할 수 있다.
- Controller 호춣하여 강제 실행,