스프링 배치 잡을 실행할 때 MyBatis 쿼리 실행 부분에서 다음과 같은 오류가 발생하는 경우가 있었다.
cannot change the ExecutorType when there is an existing transaction
이 에러는 존재하는 트랜잭션이 있을 경우 MyBatis의 ExecutorType (SIMPLE, BATCH, REUSE)
을 변경할 수 없다는 의미이다.
원인
스프링 배치 잡에서만 날 수 있는 오류는 아니고 MyBatis를 사용하고 트랜잭션 설정된 부분이 있다면 발생할 수 있을 것이다.
트랜잭션으로 묶여있는 범위 내에서는 배치 잡 내에서 동일 데이터 소스에 대해서는 동일 SqlSessionTemplate
을 사용하게 될 것인데,ExecutorType
은 SqlSessionTemplate
에 종속적인 설정 값이다.
그러다보니 ExecutorType
이 다른 동일 데이터 소스를 사용해도 트랜잭션 때문에 이전 ExecutorType
의 SqlSessionTemplate
이 사용되기 때문에 위 오류가 발생한다.
해결 방법
해결하는 방법은 상황에 따라 다르겠지만 만약 동일 ExecutorType
을 사용하도록 맞추려고 한다면,
다른 ExecutorType
을 사용한 DAO에 동일한 ExecutorType
을 가진 SqlSessionTemplate
을 사용하도록 설정하면 된다.
예를 들어서, BATCH 타입으로 트랜잭션이 수행되다가 SIMPLE 타입을 사용하는 DAO 메소드 하나가 실행되어 에러가 발생했다면,
그 DAO에 다음과 같이 설정해주면 된다.
<bean id="personDAO" class="com.sheerheart.dao.PersonDAO">
<property name="sqlSessionTemplate" ref="sqlSessionTemplate-batch" />
</bean>
<bean id="sqlSessionTemplate-batch" class="org.mybatis.spring.SqlSessionTemplate" destroy-method="clearCache">
<constructor-arg index="0" ref="sqlSessionFactory"/>
<constructor-arg index="1" value="BATCH"/>
</bean>
만약 MapperScan을 사용하고 있어서 DAO 인터페이스만 존재하는 상황이라면 다음과 같이 하면 된다.
<bean id="personDAO" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="com.sheerheart.dao.PersonDAO"/>
<property name="sqlSessionTemplate" ref="sqlSessionTemplate-batch"/>
</bean>
<bean id="sqlSessionTemplate-batch" class="org.mybatis.spring.SqlSessionTemplate" destroy-method="clearCache">
<constructor-arg index="0" ref="sqlSessionFactory"/>
<constructor-arg index="1" value="BATCH"/>
</bean>
만약 같은 트랜잭션에 묶이지 않아도 되는 것이라면 트랜잭션에 묶이지 않도록 제외 처리하는 등의 방법이 있다.
'개발 > Spring' 카테고리의 다른 글
Spring KerberosRestTemplate 사용 예제 (0) | 2021.01.08 |
---|---|
Spring Controller에서 파라미터 검증 방법들 (0) | 2020.06.18 |
스프링 @Async를 통한 비동기 처리 및 설정값 (0) | 2020.06.03 |
Spring Batch skip 로직 동작 방식 (0) | 2017.04.24 |
Spring Batch commit-interval에 대한 정리 (0) | 2016.12.23 |