728x90
반응형
MyBatis 동적 SQL에서 <iterate> 태그로 년도 리스트 처리하기 (에러 해결기)
문제 상황
통계 화면에서 여러 개의 년도를 IN 절에 넣어야 해서 MyBatis <iterate> 태그를 사용했다. 아래처럼 매퍼를 작성하고 실행했는데 에러가 발생했다.
<select id="selectYearStatistics" resultClass="map">
SELECT YEAR, COUNT(*)
FROM STATS_TABLE
WHERE YEAR IN
<iterate property="yearList" open="(" close=")" conjunction=",">
#yearList[]#
</iterate>
</select>
Map<String, Object> param = new HashMap<>();
param.put("yearList", Arrays.asList("2023", "2024"));
실행 시 다음과 같은 에러가 발생했다.
Caused by: java.sql.SQLException: ORA-00907: missing right parenthesis
-- 또는 --
Caused by: java.sql.SQLException: Invalid column index
원인 분석
<iterate>태그 안의 플레이스홀더(#yearList[]#)를 잘못 사용했거나, 콤마 처리가 빠져서 SQL 문법 오류가 발생했다.- MyBatis에서 리스트를 바인딩할 때는 conjunction(구분자) 옵션을 써야 한다.
- 실제 실행된 SQL을 로그로 확인하지 않으면 원인 파악이 어렵다.
해결 방법
코드를 아래처럼 수정했다.
<select id="selectYearStatistics" resultClass="map">
SELECT YEAR, COUNT(*)
FROM STATS_TABLE
WHERE YEAR IN
<iterate property="yearList" open="(" close=")" conjunction=",">
#yearList[]#
</iterate>
</select>
실제 실행된 SQL:
SELECT YEAR, COUNT(*)
FROM STATS_TABLE
WHERE YEAR IN ('2023','2024');
또는 MyBatis 3.x에서는 <foreach> 태그 사용이 권장된다.
<select id="selectYearStatistics" resultType="map">
SELECT YEAR, COUNT(*)
FROM STATS_TABLE
WHERE YEAR IN
<foreach item="year" collection="yearList" open="(" separator="," close=")">
#{year}
</foreach>
</select>
배운 점
동적 리스트 바인딩 시 conjunction / separator 속성을 명시해야 한다. 가능하면 <foreach>를 사용하는 것이 더 안전하고 가독성이 좋다.
728x90
반응형
'언어 > DB 관련' 카테고리의 다른 글
| 숫자 정렬 오류 (0) | 2022.09.28 |
|---|---|
| Intellij 환경에서 JPA / Hibernate 설정 (0) | 2021.05.13 |
| [ORACLE] DECODE 함수로 원하는 값 우선순위 정렬 (0) | 2020.06.26 |