JSTL처럼 mybatis에서도 SQL문을 좀 더 동적으로 효율적으로 사용할 수 있는 기능들을 지원한다.


◆ 동적 명령문

Mybatis의 sql문 안에서 특정 상황에 따라 조건태그를 이용하여 쿼리를 좀 더 다양하게 사용할 수 있도록 하는 기능


▶ 동적명령문의 종류

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach


▶ 동적명령문 특징

  • 동적태그에 들어가는 조건의 값들은 Map객체나 VO객체를 이용하여 지정한 변수명과 매치시켜 전달한다.
  • 동적명령태그에서 조건설정은 test옵션을 이용하여 지정한다.
  • test옵션의 비교 문법은 DB문법을 따른다.
  • 동적태그는 문법적 오류를 잘 고려해서 만들어야 한다.

동적 명령문은 최소한의 SQL명령어로 여러 상황을 제어할 수 있다는 장점이 있지만, 그만큼 동적명령태그를 사용할 경우 문법적인 오류에 대해 더욱 신경써서 작성해야 한다.
( 여러개의 동적명령 태그들이 있을 경우 합쳐질 때의 SQL문의 오류사항들을 잘 고려해서 만들어야 함 )


◆ if

JAVA의 단일 if문과 동일한 작동형태이다. <if>태그의 test조건에 만족하는 경우에 합쳐지는 SQL문을 작성할 수 있다.

<select id="searchCoupons" resultType="hashmap">
    select * from coupon
    <if test="limit != null">
        where limit=#{limit}
    </if>
    <if test="limit != null and max != null">
        and max &gt;= #{max}
    </if>
</select>
  • map의 키값에 ‘limit’가 없을 경우 : select * from coupon 실행
  • map의 키값에 ‘limit’가 있을 경우 : select * from coupon where limit=? 실행
  • map의 키값에 ‘limit’와 ‘max’가 있을 경우 : select * from coupon where limit=? and max > ?
    ( if태그 두개 모두 작동 )


◆ choose ( when, otherwise )

JAVA의 if/elseif/else문 또는 switch/case문과 동일한 작동 형태
when태그의 test조건에 만족하는 결과가 없다면 otherwise가 실행된다.

<select id="searchCoupons" resultType="hashmap">
    select * from coupon where number=#{number}
    <choose>
        <when test="limit != null and max != null">
            and max &gt;=#{max}
        </when>
        <otherwise>
            order by asc
        </otherwise>
    </choose>
</select>
  • map의 키값에 ‘limit’와 ‘max’가 둘 다 존재하는 경우 : select * from coupon where number=? and max >= ?;
  • map의 키값에 ‘limit’와 ‘max’둘 중 하나라도 없는 경우 : select * from coupon where number=? order by asc
  • map의 키값에 ‘number’이 없는 경우 : 에러


◆ where

<where>태그 안에 <if>태그의 조건이 하나라도 일치하면 자동으로 where키워드를 붙여주는 태그다. 즉, where태그 안에서 where키워드를 쓰지 않는다.
또한 가장 처음 붙여진 if태그 절은 앞에 and나 or키워드가 있을 시 자동으로 삭제처리 되기 때문에 모든 where태그안의 if태그에는 and나 or을 붙여도 상관이 없다.

<select id="findlog_2" resultType="hashmap">
    select * from coupon
    <where>
        <if test="limit != null">
            and limit = #{limit}
        </if>
        <if test="max != null">
            and max = #{max}
        </if>
    </where>
</select>
  • map의 키값에 ‘limit’나 ‘max’가 없을 시 : select * from coupon 실행
  • map의 키값에 ‘limit’만 있을 시 : select * from coupon where limit = ? 실행
  • map의 키값에 ‘max’만 있을 시 : select * from coupon where max = ? 실행
  • map의 키값에 ‘limt’와 ‘max’가 둘 다 있을 시 : select * from coupon where limit=? and max=? 실행


◆ set

where와 마찬가지로 if조건에 하나라도 일치하는 값이 있다면 자동으로 set키워드를 붙여주는 태그로 update문에서만 사용이 가능하다.
또한 set태그는 마지막 붙여진 요소의 콤마(,)를 자동으로 삭제해 주기 때문에 모든 요소에 콤마를 붙여도 무방하다.

<update id="updateAccount">
    update account
    <set>
        <if test="nick != null">nick =#{nick},</if>
        <if test="profile != null">profile =#{profile},</if>
        <if test="pass != null">pass =#{pass},</if>
    </set>
    from id=#{id}
</update>


◆ trim

where태그나 set태그처럼 자동적으로 삽입하거나 문법에 맞게 자동으로 삭제되는 기능을 수동적으로 설정할 수 있게 해주는 태그
마찬가지로 내부 if조건이 하나라도 만족해야 실행된다.

ex) set태그를 trim으로 만든 예

<update id="updateAccount2">
    update account
    <trim prefix="set" suffix="" prefixOverrides=" " suffixOverrides=",">
        <if test="nick != null">nick =#{nick},</if>
        <if test="profile != null">profile =#{profile},</if>
        <if test="pass != null">pass =#{pass},</if>
    </trim>
</update>
  • prefix

    : 맨 앞에 추가할 단어

  • suffix

    : 맨 뒤에 추가할 단어

  • prefixOverrides

    : 가장 처음 들어갈 sql문에서 삭제할 앞 글자

  • suffixOverrides

    : 가장 뒤에 들어갈 sql문에서 삭제할 뒷 글자


◆ foreach

sql명령문의 반복 처리로 구문을 만들어낼 수 있는 태그
List나 Set계열의 컬렉션 객체를 통해 많은 값을 한번에 넘겨줄 수 있다.

<select id="findroom" resultType="hashmap">
    select * from chatroom
    <if test="cate2 != null">
        where cate2 in
        <foreach collection="cate2" item="c" open="(" close=")" separator=",">
            #{c}
        </foreach>
    </if>
</select>
  • collection

    : 넘겨줄 map의 킷값

  • item

    : 넘겨받은 키의 value를 셋팅 할 변수 ( sql문 안에서 쓰일 변수 )

  • open

    : 해당 foreach반복문 돌입 전에 들어갈 문구

  • close

    : 해당 foreach반복문이 끝난 후 들어갈 문구

  • separator

    : foreach반복문의 매 반복 마다 끝에 반복적으로 계속 들어갈 문구

※ foreach의 값은 list나 set 또는 배열만 보낼 수 있다.
단, 넘겨주는 형태는 Map으로 넘겨준다
ex ) Map(K, List) 또는 Map(K, Set) 또는 Map(K, Array)


◆ selectKey

쿼리문에서 테이블 컬럼값이 필요한 경우에 서브쿼리처럼 사용하여 변수를 셋팅할 수 있는 태그

<insert id="insertBoard" parameterType="Board">
    <selectKey resultType="string" keyProperty="boardID" order="BEFORE">
        SELECT MAX(boardID)+1 FROM board        
    </selectKey>    
    INSERT INTO board(boardID, title, content)
    VALUES(#{boardID}, #{title}, #{content})
</insert>  


◆ <![CDATA[]]>

CDATA는 CDATA안에서 사용되는 쿼리의 모든 문자를 문자열로 치환시켜준다. 따라서 <, >등 태그를 열고 닫는 의미로 인식될 수 있는 충돌문제를 방지시키기 위해 사용한다.

<select id="findAll" resultMap="MemberResultMap">
    <![CDATA[
        select * from employees where salary > 100
    ]]>
</select>

또는

<select id="findAll" resultMap="MemberResultMap">
    select *
    from employees
    where salary <![CDATA[>]]> 100
</select>

<> 연산자는 !=와 같다. 따라서 둘다 사용해도 무방하다