본문 바로가기
DataBase/MyBatis

[MyBatis] 동적 SQL

by 김뚱 2019. 5. 24.

XML element를 사용해서 동적 SQL을 처리하다보면 분기가 많아지는 경향이 자주 발견된다. 

 

이는 가독성이 떨어지고 오타가 발생할 확률이 높아지므로 버그가 발생하는 일이 많아지게 된다.

 

따라서 ibatis에서 제공하던 10개 이상의 XML element를 MyBatis에서는 4개의 element로 줄였다.

 

MyBatis는 XML element를 줄이고 다양한 조건을 처리하기 위해 OGNL 표현식을 사용한다.

 

(jsp에서 주로 사용하는 JSTL 표현식이 OGNL이기 때문에 이를 사용하던 개발자는 MyBatis의 조건문에 적용하면 된다.)

 

XML에서 동적 SQL을 위한 element를 사용하여 생성하는 방법은 아래와 같다.

 

1. OGNL (Object Graph Navigation Language)

OGNL은 property의 값을 가져오거나 설정하기 위한 언어이다.

JSTL core 라이브러리에서 if 태그의 조건문을 표현할 때 가장 많이 사용한다.

분기처리를 위한 표현식에 OGNL을 많이 사용한다.

<%@ taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>
<c:if test="${obj.val != null}">

 

 

2. MyBatis element

 

(1) if

if element를 사용하면 조건에 대해 처리하고 만족하는 결과를 모두 적용한다.

<select id="selectMember" parameterType="map", resultType="map">
    SELECT  USER_NO
            USER_ID
            NAME
            REG_DT
    FROM    USER
    <if test "userNo != null">
    WHERE 	USER_NO = #{userNo}
    </if>
    <if test "name != null">
    WHERE 	NAME = #{name}
    </if>
</select>

위에 작성한 if 코드는 사용자번호와 이름이 모두 있을 경우 결과 SQL은 where절이 두 번 생성되므로 문법 에러가 발생한다. 만약 where element를 사용하였을 때 두번째 조건부터 충족하는 경우에는 SQL은 다음과 같다.

<select id="selectMember" parameterType="map", resultType="map">
    SELECT  USER_NO
            USER_ID
            NAME
            REG_DT
    FROM    USER
    <where>
    	<if test "userNo != null">
    	USER_NO = #{userNo}
    	</if>
    	<if test "name != null">
    	AND NAME = #{name}
    	</if>
    </where>
</select>
SELECT 	USER_NO
   	USER_ID
  	NAME
        REG_DT
FROM	USER
WHERE
    	NAME = #{name}

where element의 역할은 WHERE 구문을 붙이고 하위 element에서 생성한 내용이 AND나 OR로 시작할 경우 자동으로 지워준다. 그러나 AND나 OR가 아닌 다른 문자로 시작하는 경우에는 trim element를 사용한다.

 

 

(2) choose(when, otherwise)

choose 하위의 when element에서 만족하는 조건이 하나라도 나오면 해당 조건의 결과를 동적 SQL에 적용한다. 

그러나 만족하는 조건이 없다면 other element의 결과를 동적 SQL에 적용한다.

<select id="selectMember" parameterType="map", resultType="map">
    SELECT  USER_NO
            USER_ID
            NAME
            REG_DT
    FROM    USER
    <choose>
    	<when test "userNo != null">
    	WHERE USER_NO = #{userNo}
    	</when>
        <when test "name != null">
        WHERE NAME = #{name}
        </when>
        <otherwise>
        WHERE USER_NO = 1
        AND USER_ID = 'id01'
        </otherwise>
    </choose>
</select>

위에 작성한 if 코드는 사용자번호와 이름이 모두 있을 경우 결과 SQL은 where절이 두 번 생성되므로 문법 에러가 발생한다. 

 

(3) trim(where, set)

trim element는 if element의 단점을 보완할 수 있는 기능을 제공한다.

<select id="selectMember" parameterType="map", resultType="map">
    SELECT  USER_NO
            USER_ID
            NAME
            REG_DT
    FROM	USER
    <trim prefix="WHERE" prefixOverrides="AND|OR">
    	<if test "userNo != null">
    	AND USER_NO = #{userNo}
    	</if>
      	<if test "name != null">
      	AND NAME = #{name}
      	</if>     
    </trim>
</select>

 

trim 속성

- prefix : 실행 후 element의 내용이 있으면 가장 앞에 붙여준다.

- prefixOverrides : 실행 후 element 내용 중 가장 앞에 해당하는 문자들이 있으면 자동으로 지워준다.

- suffix : 실행 후 element의 내용이 있으면 가장 뒤에 붙여준다.

- suffixOverrides실행 후 element 내용 중 가장 뒤에 해당하는 문자들이 있으면 자동으로 지워준다.

 

trim element는 select, insert, update, delete에 사용가능하다.

<update id="updateMember" parameterType="map", resultType="map">
    UPDATE  USER
    <trim prefix="SET" suffixOverrides=",">
    	<if test "userId != null">
    	USER_ID = #{userId},
    	</if>
      	<if test "name != null">
      	NAME = #{name}
      	</if>     
    </trim>
    WHERE   USER_NO = #{userNo}
</update>

set element는 마지막으로 명시된 칼럼 표기에서 쉼표를 자동으로 제거한다. 그러나 이는 trim element로 대체 가능하기 때문에 trim을 사용하는 경우가 더 많다.

 

 

(4) foreach

SQL의 조회 조건에는 IN절로 조건을 추가하는 경우가 있다.

<select id="selectMember" parameterType="map", resultType="map">
    SELECT  USER_NO
            USER_ID
            NAME
    FROM    USER
    <trim prefix="WHERE" prefixOverrides="AND|OR">
    	<if test "userNo != null">
    	USER_NO IN
        <foreach collection="userNos" item="userNo" index="index" open="(" close=")" separator=",">
            #{userNo}
        </foreach>
    	<if>
    </trim>    
</select>

foreach 속성

- collection : 값 목록을 가진 객체를 설정한다. 

item : 목록에서 각각의 값을 사용하는 속성이다.

index : 몇 번째 값인지 나타내는 인덱스 값이다. 시작값은 0이다.

open : 목록에서 값을 가져와서 설정할 때 가장 앞에 붙여 주는 문자를 지정하는 속성이다.

close : 목록에서 값을 가져와서 설정할 때 가장 뒤에 붙여 주는 문자를 지정하는 속성이다.

separator : 목록에서 값을 가져와서 설정할 때 값들 사이에 붙여 주는 문자를 지정하는 속성이다.

 

728x90
반응형

'DataBase > MyBatis' 카테고리의 다른 글

[MyBatis] Spring의 데이터베이스 관련 설정  (0) 2019.05.23
[MyBatis] MyBatis란?  (0) 2019.05.22

댓글