티스토리 뷰

Spring-Batch로 개발을 진행하던 중 아래와 같은 오류를 접하였다.
org.springframework.dao.TransientDataAccessResourceException: Cannot change the 
ExecutorType when there is an existing transaction


현상은 "Transaction내에서 ExecutorType이 변경될 수 없다” 이다.
위 현상은 Batch 처리를 할 때 발생할 수 있다. 그 이유는 아래와 같다.
  • MybatisPagingItemReader를 사용하면 내부적으로 SqlSessionTemplate이 생성될 때 ExecutorType.BATCH로 지정된다.
  • 만약 MybatisPagingItemReader에서 다른 쿼리를 날려보고자 한다면 기본적으로 ExecutorType.SIMPLE이기 때문에 문제가 될 수 있다.

무슨 말인가 이해가 안 될 수 있으니 코드로 살펴보자.
MyBatisPagingItemReader<MyModel> reader = null;
try {
    Map<String, Object> params =
new HashMap<String, Object>();
    params.put(
"nowDate", commonRepository.now());

    reader =
new MyBatisPagingItemReader<MyModel>();
    reader.setSqlSessionFactory(
this.sqlSessionFactory);
    reader.setQueryId(
           
“com.study.mybatis.common.MyRepository.select");
    reader.setParameterValues(params);
    reader.setPageSize(1000);

}
catch (Exception e) {
    e.printStackTrace();
}

return reader;


Mybatis 기본 설정에서는 ExecutorType.SIMPLE이 기본이다. 따라서 CommonRepository.now()에서는 SIMPLE로 동작한다.
하지만 MybatisPagingItemReader의 경우는 ExecutorType.BATCH로 SqlSessionTemplate을 생성하고 있다.
public void afterPropertiesSet() throws Exception {
  super.afterPropertiesSet();
  Assert.notNull(this.sqlSessionFactory);
  this.sqlSessionTemplate = new SqlSessionTemplate(this.sqlSessionFactory, ExecutorType.BATCH);
  Assert.notNull(this.queryId);
}


Transaction 설정이 있다면 ExecutorType이 SIMPLE에서 BATCH로 변경되기 때문에 오류가 발생할 수 있다.
이를 해결하는 방법은 3가지 정도로 생각된다.
  1. NOW()를 Java코드로 변경하는 것이다.
    즉, sql을 수행하지 않고 처리하는 방법으로 오류를 발생시키는 코드를 원천 제거하는 방법이다.
  2. sqlSessionFactory.openSession()을 사용하는 방법
    sqlSessionFactory.openSession().selectOne(“commonRepository.now”)로 처리하면 된다.
  3. CommonRepository를 별도의 Spring Bean으로 감싸 Transaction을 분리 또는 적용하지 않는 방법
    별도의 Bean으로 분리 후 @Transactional(propagation = Propagation.NOT_SUPPORTS)로 설정해도 해결할 수 있다.
    REQUIRES_NEW로 하여도 가능하나. select에 Transaction을 생성하는 것이 맘에 들지 않는다.

3가지 모두 맘에 들진 않지만 개인적으로는 3번이 그나마 낫다고 생각한다.
별도의 클래스가 만들어져야 하지만 Job 코드에서는 깔끔하게 보이기 때문이다.

추가적으로 SpringBatch에서 ExecutorType에는 3가지가 있다.
  • SIMPLE: executor가 별도의 작업을 하지 않음.
  • REUSE: prepared statement 재사용
  • BATCH: prepared statement 재사용 & 묶음 갱신

위에서도 언급했지만 기본값은 SIMPLE이다. 특별한 경우가 없는 한 SIMPLE을 사용하겠으나, 묶음 처리를 하는 경우는 BATCH를 사용하는 경우도 있다.

참고

'Programing > Spring-Batch' 카테고리의 다른 글

Spring-Batch commit-interval 설정  (0) 2016.03.19
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함