cannot change the executortype when there is an existing transaction
스프링 배치를 활용하여 개발하다가 만난 에러를 정리합니다.
저 에러 메세지의 의미는 "한 트랜잭션안에서 ExecutorType을 변경할 수 없습니다." 라는 뜻이다.
우선 ExecutorType은 3가지가 존재하는데 간단하게 정리하자면 아래와 같다.
- ExecutorType.SIMPLE: 이 타입의 실행자는 아무것도 하지 않는다. 구문 실행마다 새로운 PreparedStatement를 생성한다.
- ExecutorType.REUSE: 이 타입의 실행자는 PreparedStatements를 재사용할 것이다.
- ExecutorType.BATCH: 이 실행자는 모든 update구문을 배치처리하고 중간에 select 가 실행될 경우 필요하다면 경계를 표시한다. 이러한 과정은 행위를 좀더 이해하기 쉽게 하기 위함이다.
필자는 스프링 배치 내 Reader-Writer 구조를 사용할 때,
MybatisPagingItemReader를 사용하고 별도의 CustomWriter를 생성하여 개발을 진행한다.
MybatisPagingItemReader와 CustomWriter가 동일한 SqlSessionFactory를 주입받아 작업을 진행하는 상황이였다.
발생 원인
프로젝트 설정, 환경에 따라 모두 다르겠지만 우선 ExecutorType의 기본값은 SIMPLE 임을 인지하자.
그렇다면 마이바티스 라이브러리인 MybatisPagingItemReader는 어떠할까?
if (sqlSessionTemplate == null) {
sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory, ExecutorType.BATCH);
}
BATCH 타입으로 생성하고 있다.
같은 sqlSessionFactory를 사용하여 Reader/Writer의 sqlSesstionTemplate을 사용하기 때문에
Writer에서는 Simple 타입으로 작업을 시도 시 해당 에러가 발생한 것이다.
해결 방법
1. Reader/Writer에 Executor 타입을 일치시킨다.
- 당연한 이야기지만, 일치시켜 해결할 수 있다면 개인별 구성에 맞게 타입을 확인하여 일치시키면 된다.
가능한 구조라면 이게 가장 편하다.
2. 트랜잭션을 분리시킨다.
- 트랜잭션 전파 레벨을 변경해서 해결할 수도 있다고한다. (직접 써보진 않아서 참고자료를 남겨둡니다.)
https://tomining.tistory.com/178
- sqlSessionFactory를 분리하는 방법도 가능하다. BATCH 타입으로만 생성되는 sqlSessionFactory를 새로운 빈으로 등록하여 Reader에는 새로운 sqlSesstionFactory를 사용하여 Writer의 트랜잭션과 별도로 분리하는 방법도 있다.
간단하게 생각하면 타입을 바꾸지 말라는 단순한 에러이다.
MybatisPagingItemReader 가 아니더라도 내가 사용하는 라이브러리의 ExecutorType 기본값을 확인하고 내 상황에 맞게 제어하면 해결할 수 있을 것이다.
참고
'Spring' 카테고리의 다른 글
[SpringBoot] H2 데이터베이스 PostgreSQL 모드로 변경하기 (0) | 2024.03.13 |
---|---|
[Springboot] 외부에서 로컬 서버 접속하기 (0) | 2024.03.12 |
[SpringBoot] 스프링부트 - @SpringBootApplication 이해하기 (0) | 2021.08.21 |
[SpringBoot] 스프링부트 - 서버 포트번호 변경하기 (0) | 2021.08.19 |
[SpringBoot] 스프링부트 시작하기 - 프로젝트 생성 및 실행 (0) | 2021.08.16 |
댓글