스프링으로 연습삼아 혼자서 프로젝트를 하던 도중 화면에서 한번에 데이터를 여러개로 받아 그 갯수만큼 insert처리를 해야하는 기능을 구현해야했는데요, 모르는게 많은 저는 막막했습니다.. 다행히도 바로 생각난 건 막연하게 for문을 이용하는 건 어떨까? 하는 생각으로 시작했습니다.

 

구글링과 사놓은 책들을 뒤져보다 mybatis에서 foreach라는 태그를 사용하여 해결했습니다. 이 외에도 mybatis에서는 여러가지의 동적 태그들이 있습니다. if, choose, trim 등등,, 그래서 mybatis의 동적태그에 대해 복습하는 겸 정리를 해볼까 합니다.

 

정리하기 앞서 동적 태그를 좀 더 매끄럽게 사용할 수 있게 해주는 태그에 대해 먼저 알아보겠습니다. trim이라는 태그엔데, 이 태그는 단독으로 사용되지 않는다는 것이 특징입니다.

 

  • trim 태그

trim 태그는 하위에서 만들어지는 SQL문을 조사하여 추가적인 SQL을 처리해주는 태그입니다.

trim태그의 속성에 대해 몇가지 알아보겠습니다.

이름

설명

prefix

해당 태그 내에서 가장 앞에 붙음

prefixOverrides

해당 태그 내에서 쿼리가 가장 앞에 해당하는 문자를 지워줌

suffix

해당 태그 내에서 가장 뒤에 붙음

suffixOverrides

해당 태그 내의 가장 뒤에 해당하는 문자를 지워줌

 

위의 목록을 통해 예시를 들어보겠습니다.

 

 - 예시 1

SELECT COLUMN1, COLUME2 
  FROM TABLE 
 WHERE PK_COLUMN1 = #{key1}
   <trim prefix="AND (" prefixOverrides="OR" suffix=")">
     <if test="key2 != null">
     	OR PK_COLUMN2 = #{key2}
     </if>
     <if test="key3 != null">
     	OR PK_COLUMN3 = #{key3}
     </if>
   </trim>

 

위의 prefix 태그를 보면, prefix="AND ("라는 것을 볼 수 있습니다. 이는 where절의 조건을 이어주는 AND를 뜻하며, prefixOverride="OR"은 trim 태그 내의 맨 앞의 문자가 OR일 때 해당 문자를 지워주는 역할을 합니다. suffix=")"은 말 그대로 맨 뒤에 붙은 문자입니다.

 

위의 SQL문의 trim태그내의 if문이 모든 조건을 만족한다면, 해당 SQL문은 아래처럼 해석됩니다.

 

SELECT COLUMN1, COLUME2 
  FROM TABLE 
 WHERE PK_COLUMN1 = #{key1} 
       AND(PK_COLUMN2 = #{key2} OR PK_COLUMN3 = #{key3})

 

 - 예시 2

 

UPDATE TABLE
  <trim prefix="SET" suffixOverrides=",">
    <if test="key1 != null">COLUMN1 = #{key1},</if>
    <if test="key2 != null">COLUMN2 = #{key2},</if>
    <if test="key3 != null">COLUMN3 = #{key3},</if>
    <if test="key4 != null">COLUMN4 = #{key4},</if>
  </trim>

 

예시 1에 없던 suffixOverrides를 사용하였습니다. suffixOverrides는 맨 끝의 문자가 해당문자와 일치할 때 제거해주는 역할을 합니다. trim태그 안의 if문을 전부 만족하는 조건이라면 해당 SQL문은 아래처럼 해석됩니다.

UPDATE TABLE SET 
COLUMN1 = #{key1},
COLUMN2 = #{key2},
COLUMN3 = #{key3},
COLUMN4 = #{key4}

 

trim 태그정리는 이정도로 마치고, 본격적인 동적 태그들에 대해 알아보겠습니다.

 

  • if

if는 조건이 true가 되었을 때 태그 내의 SQL문을 처리합니다.

 

<if test="key1 != null">
  COLUMN1 = #{key1}
</if>

위처럼 해당 if문의 test가 true일 때, 태그 내의 SQL문을 출력합니다.

 

  • choose

if와 달리 choose는 여러 상황들 중 하나의 상황에서만 동작합니다. 마치 Java의 if ~ else와 유사합니다.

<choose>
    <when test="key1 != null">
    	COLUMN1 = #{key1}
    </when>
	<when test="key2 != null">
    	COLUMN2 = #{key2}
    </when>
	<when test="key3 != null">
    	COLUMN3 = #{key3}
    </when>
    <otherwise>
    	COLUMN4 = #{key4}
    </otherwise>
</choose>

 

위의 choose태그 안에서 when이라는 태그가 있습니다. 이는 조건식을 뜻하며 Java에서 else if와 유사한 의미를 가집니다. choose태그의 마지막 otherwise는 Java의 else와 유사한 의미를 가지며, choose태그 내에서 when태그의 조건의 나머지를 뜻합니다.

 

  • foreach

foreach태그를 알아보기 전 foreach태그의 속성에 대해서 먼저 알아볼 필요가 있습니다.

이름

설명

collection

전달받은 인자이며, List 또는 Array만 사용 가능

item

전달받은 인자 값을 alias명으로 설정

open

구문이 시작될 때 입력 할 문자열

close

구문의 맨 마지막에 입력 할 문자열

separator

반복되는 사이에 입력 할 문자열

index

반복되는 구문 번호로, 0부터 순차적으로 증가함

 

아래 예시를 보겠습니다.

 

SELECT COLUMN1, COLUMN2
  FROM TABLE
 WHERE COLUMN1 in
    <foreach item="item" index="index" collection="list" open="(" seperator="," close=")">
    	#{item}
    </foreach>

 

전달받은 파라미터의 타입은 list이고, list의 alias설정은 item의 "item"으로 설정하였습니다. foreach태그 맨 앞과 끝은 "(", ")"이며, 반복될때마다 ","를 붙이게 됩니다.

 

만약 배열의 길이가 2인 list의 배열이라고 가정한다면,

 

SELECT COLUMN1, COLUMN2
  FROM TABLE
 WHERE COLUMN1 in (#{item[0]}, #{item[1]})

위와 같은 결과를 출력합니다.

 

 

 

 

마치며,

 

사실 foreach문에 대해 자세히 알아보려했는데, 글이 너무 길어질 것 같아 따로 포스팅을 하기로 결정했습니다. 개인적으로 위의 태그 중 foreach와 trim을 좀 까다로워했었고, 단순한 SQL문이라면 모를까, 조금 복잡해지기라도 저처럼 숙련도가 없는 사람들은 오랜시간 고민을 해야합니다.

 

다행히도 주관적으로 mybatis는 직관적인 언어라고 생각해서 그런지 그 구조가 복잡한거라고는 생각하지 않지만, 다음 foreach태그를 중점적으로 포스팅 할 때에는 혼자 고민했었던 사례를 예시로 어떻게 풀어나갔는지 적어보려 합니다.

 

 

 

 

 

참고자료

코드로 배우는 스프링 웹 프로젝트(이병승) www.yes24.com/Product/Goods/64340061

java119.tistory.com/85

kim0404.tistory.com/19

java119.tistory.com/103

'코딩 > Spring' 카테고리의 다른 글

Spring Model  (1) 2020.08.28
Spring Connection Pool(DBCP), Hikari CP  (0) 2020.08.24
Spring servlet-context.xml, root-context.xml, web.xml  (0) 2020.08.23
Spring Lombok Log4j 오류뜰 때  (2) 2020.08.21
Spring 스프링을 사용하는 이유  (0) 2020.08.20
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기