MyBitis-동적쿼리처리
이번 포스팅은 MyBatis에서 동적으로 쿼리를 처리하는 방법입니다.
1. mybatis에서 사용하는 동적 SQL의 종류
mybatis에서 동적으로 쿼리를 처리하는 방법은 아래 4가지가 있습니다.
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
- if 요소
특정 조건이 참일 때에만 해당 SQL 문장을 포함합니다.
<select id="findUserByCondition" parameterType="map" resultType="User">
SELECT *
FROM users
WHERE 1=1
<if test="name != null">
AND name = #{name}
</if>
<if test="age != null">
AND age = #{age}
</if>
</select>
-
장점: 간단한 조건문을 처리하는 데 적합하며, 읽기 쉽고 유지보수하기 쉽습니다.
-
단점: 복잡한 논리를 처리할 때는 여러 개의 if 문이 필요하여 코드가 길어질 수 있습니다.
- choose(when, otherwise)
조건에 따라 서로 다른 SQL 문장을 실행합니다. (switch-case 문과 유사)
<select id="findUserByStatus" parameterType="map" resultType="User">
SELECT *
FROM users
WHERE 1=1
<choose>
<when test="status == 'active'">
AND status = 'active'
</when>
<when test="status == 'inactive'">
AND status = 'inactive'
</when>
<otherwise>
AND status = 'unknown'
</otherwise>
</choose>
</select>
-
장점: 여러 조건 중 하나를 선택해야 할 때 유용하며, 가독성이 좋습니다.
-
단점: 복잡한 경우에서는 많은 when 문이 필요할 수 있습니다.
- where 요소
불필요한 AND 또는 OR을 자동으로 제거하여, 조건문에서 WHERE 절을 보다 편리하게 관리 가능합니다. 만약 where 요소가 기대하는 바와 다르게 동작한다면 trim 요소를 정의하여 사용합니다.
<select id="findUserByDynamicWhere" parameterType="map" resultType="User">
SELECT *
FROM users
<where>
<if test="name != null">
name = #{name}
</if>
<if test="age != null">
AND age = #{age}
</if>
</where>
</select>
-
장점 : 동적으로 조건을 추가할 때 불필요한 AND, OR를 자동으로 관리해 줌 → 실수 감소
-
단점 : 복잡한 논리를 구현하는 데는 한계가 있을 수 있습니다.
- trim, set 요소
SQL 문장의 특정 부분을 트리밍하거나 동적으로 설정할 때 사용합니다. set 요소는 주로 UPDATE 문에서 동적으로 필드를 설정할 때 유용합니다.
<update id="updateUser" parameterType="User">
UPDATE users
<set>
<if test="name != null">
name = #{name},
</if>
<if test="age != null">
age = #{age},
</if>
</set>
WHERE id = #{id}
</update>
- 장점 : 불필요한 쉼표(,)나 접두어/접미어를 관리하여 SQL 문장의 형식을 자동으로 정리해줍니다.
- 단점 : 단순한 경우에는 오히려 복잡해 보일 수 있습니다.
- foreach 요소
리스트나 배열 같은 컬렉션을 반복하여 SQL 문을 생성할 때 사용하고, 주로 IN 절이나 다중 삽입 시 유용합니다.
<select id="findUserByIds" parameterType="list" resultType="User">
SELECT *
FROM users
WHERE id IN
<foreach collection="list" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
- 장점 : 다수의 파라미터를 처리할 때 매우 편리하며, 반복적인 SQL 생성 작업을 간단하게 처리할 수 있습니다.
- 단점 : 컬렉션의 크기가 매우 클 경우, 성능 이슈가 발생할 수 있습니다.
2. 동적 SQL이 필요한 이유
- 유연한 쿼리 작성
동적 SQL을 사용하면 입력 파라미터나 조건에 따라 SQL 쿼리를 유연하게 작성할 수 있습니다. 고정된 쿼리로는 처리할 수 없는 다양한 요구사항을 쉽게 처리할 수 있어 복잡한 비즈니스 로직을 SQL 쿼리에서 직접 구현할 수 있습니다.
- SQL 재사용성 증가
동적 SQL을 통해 하나의 매퍼 XML 파일에서 다양한 조건에 따라 여러 쿼리를 생성할 수 있습니다. 이로 인해 중복 코드를 줄이고, 유지보수성을 높일 수 있습니다.
- 복잡한 쿼리의 간소화
복잡한 조건이 필요한 쿼리에서, 동적 SQL을 사용하면 코드가 간결해지고 유지보수가 쉬워집니다. 기존 쿼리에 조건을 추가하거나 제거하는 작업이 훨씬 간단해집니다.
3. 동적 SQL의 단점
- 복잡성 증가
동적 SQL을 과도하게 사용하면 XML 파일이 복잡해지고, 가독성이 떨어질 수 있습니다. 또한 디버깅이 어려워질 수 있습니다.
- 성능 저하 가능성
동적 SQL을 많이 사용할 경우, 특히 foreach 요소 등을 통해 많은 데이터를 처리할 때 성능 저하가 발생할 수 있습니다. 적절한 인덱싱이나 캐싱 전략이 필요할 수 있습니다.
- 디버깅의 어려움
동적 SQL은 SQL 문이 런타임에 생성되기 때문에, 잘못된 SQL이 생성되었을 경우 디버깅이 어려울 수 있습니다. 이로 인해 쿼리 실행 시 오류를 파악하는 데 시간이 더 걸릴 수 있습니다.
참고
[1] MyBatis 공식 문서