2024-08-30,   김혜원

이번 포스팅은 MyBatis에서 동적으로 쿼리를 처리하는 방법입니다.


 

1. mybatis에서 사용하는 동적 SQL의 종류

mybatis에서 동적으로 쿼리를 처리하는 방법은 아래 4가지가 있습니다.

  1. if
  2. choose (when, otherwise)
  3. trim (where, set)
  4. foreach

 

  1. 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 문이 필요하여 코드가 길어질 수 있습니다.

 

  1. 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 문이 필요할 수 있습니다.

 

  1. 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를 자동으로 관리해 줌 → 실수 감소

  • 단점 : 복잡한 논리를 구현하는 데는 한계가 있을 수 있습니다.

 

  1. 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 문장의 형식을 자동으로 정리해줍니다.
  • 단점 : 단순한 경우에는 오히려 복잡해 보일 수 있습니다.

 

  1. 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이 필요한 이유

  1. 유연한 쿼리 작성

동적 SQL을 사용하면 입력 파라미터나 조건에 따라 SQL 쿼리를 유연하게 작성할 수 있습니다. 고정된 쿼리로는 처리할 수 없는 다양한 요구사항을 쉽게 처리할 수 있어 복잡한 비즈니스 로직을 SQL 쿼리에서 직접 구현할 수 있습니다.

 

  1. SQL 재사용성 증가

동적 SQL을 통해 하나의 매퍼 XML 파일에서 다양한 조건에 따라 여러 쿼리를 생성할 수 있습니다. 이로 인해 중복 코드를 줄이고, 유지보수성을 높일 수 있습니다.

 

  1. 복잡한 쿼리의 간소화

복잡한 조건이 필요한 쿼리에서, 동적 SQL을 사용하면 코드가 간결해지고 유지보수가 쉬워집니다. 기존 쿼리에 조건을 추가하거나 제거하는 작업이 훨씬 간단해집니다.

 

 

3. 동적 SQL의 단점

 

  1. 복잡성 증가

동적 SQL을 과도하게 사용하면 XML 파일이 복잡해지고, 가독성이 떨어질 수 있습니다. 또한 디버깅이 어려워질 수 있습니다.

   

  1. 성능 저하 가능성

동적 SQL을 많이 사용할 경우, 특히 foreach 요소 등을 통해 많은 데이터를 처리할 때 성능 저하가 발생할 수 있습니다. 적절한 인덱싱이나 캐싱 전략이 필요할 수 있습니다.

 

  1. 디버깅의 어려움

동적 SQL은 SQL 문이 런타임에 생성되기 때문에, 잘못된 SQL이 생성되었을 경우 디버깅이 어려울 수 있습니다. 이로 인해 쿼리 실행 시 오류를 파악하는 데 시간이 더 걸릴 수 있습니다.

 

 


참고

[1] MyBatis 공식 문서

[2] [MyBatis] 동적 쿼리 SQL (if, choose, when,set , foreach ..)

업데이트: