본문 바로가기
Programming/Java * Spring

[Java] MyBatis 동적 쿼리 - trim, where, set

by 고막고막 2022. 6. 27.

검색 또는 업데이트 조건을 동적으로 받는 경우 자주 사용하는 MyBatis 문법에 대해 정리해보고자 한다.

 

1. <where>

  • <if> 태그만 사용할 때는 각각의 조건들만 동적으로 추가 가능했지만,  <where> 태그를 사용하게 되면 <where> 태그 하위의 <if> 태그 리턴 값에 따라 조건문 자체를 동적으로 active 시킬 수 있다.
  • 하위의 <if> 태그 값을 모두 충족하지 않으면 WHERE가 생기지 않고 SQL 종결되며, 하나라도 충족하면 SQL에 WHERE가 붙는다.
  •  하위 <if> 태그에는 AND || OR 모두 받을 수가 있다. 
  • 불필요한 AND 또는 OR 구문을 제거해준다.

 

  1) <where> 태그 사용하지 않을 때 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<select id="findActiveBlogLike" resultType="Blog">
  SELECT * 
  FROM BLOG
  WHERE
  <if test="state != null">
    state = #{state}
  </if>
  <if test="title != null">
    AND title like #{title}
  </if>
  <if test="author != null and author.name != null">
    AND author_name like #{author.name}
  </if>
</select>
cs

     <if> 안의 모든 조건이 충족하지 않는 경우 위의 구문은 아래과 같이 오류를 발생시킨다.

1
2
3
SELECT * 
FROM BLOG
WHERE
cs

 

2) <where> 태그를 사용하면

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<select id="findActiveBlogLike" resultType="Blog">
  SELECT * 
  FROM BLOG
  <where>
    <if test="state != null">
        AND state = #{state}
    </if>
    <if test="title != null">
        AND title like #{title}
    </if>
    <if test="author != null and author.name != null">
        AND author_name like #{author.name}
    </if>
  </where>
</select>
cs

     <if> 안의 모든 조건이 충족하지 않으면 구문이 아래와 같이 정상적으로 끝나게 된다.

1
2
SELECT * 
FROM BLOG
cs

     마찬가지로 AND 조건 뿐만 아니라 OR 조건도 받을 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
SELECT DISTINCT PURDOC_NO
FROM PU_PURORDERACCT_DTL         
<where>
    <if test="P_FROM_CC != null and P_FROM_CC != ''">
        OR CC_CD BETWEEN #{P_FROM_CC} AND #{P_TO_CC} 
    </if>
    <if test="P_WBS_NO != null and P_WBS_NO != ''">
        OR WBS_NO BETWEEN #{P_WBS_NO} AND #{P_WBS_NO_TO}
    </if>
    <if test="P_FROM_PM_ORD != null and P_FROM_PM_ORD != ''">
        OR PM_ORD_NO BETWEEN #{P_FROM_PM_ORD} AND #{P_TO_PM_ORD}
    </if>
    <if test="P_ASSET_CD != null and P_ASSET_CD != ''">    
        OR ASSET_CD BETWEEN #{P_ASSET_CD} AND #{P_ASSET_CD_TO}
    </if>
</where>
 
cs

 

 

2. <set>

  • <set> 태그도 <where> 태그와 마찬가지로 <set> 태그 하위의 <if> 태그 리턴 값에 따라 SET 구문을 동적으로 active 시킨다. 
  • 조건 뒤에 불필요한 쉼표(,) 를 제거해준다.
1
2
3
4
5
6
7
8
9
10
<update id="updateAuthorIfNecessary">
  update Author
    <set>
      <if test="username != null">username=#{username},</if>
      <if test="password != null">password=#{password},</if>
      <if test="email != null">email=#{email},</if>
      <if test="bio != null">bio=#{bio},</if>
    </set>
</update>
 
cs

 

3. <trim>

  • prefix : 실행될 구문의 맨 앞에 문자열을 추가
  • prefixOverrides : 실행될 구문의 맨 앞에 문자열이 존재한다면 제거
  • suffix : 실행될 구문의 맨 뒤에 문자열을 추가
  • suffixOverrides : 실행될 구문의 맨 뒤에 문자열이 존재한다면 제거
  • 위의 속성들을 활용하여 보다 복잡한 조건문을 동적으로 처리할 수 있다.

예시 1) 여러 개의 검색 조건 중 OR 검색을 해야할 때 prefixOverrides 속성을 사용해 AND 다음 OR 이 올 경우 바로 삭제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<if test="!P_SEARCH_TEXT_1.equals('%%'.toString())">
    <trim prefix="AND (" prefixOverrides="OR" suffix=")">
        <![CDATA[OR A.TLMKT_YY like #{P_TLMKT_YY_TEXT} AND A.TLMKT_SQ_SQ like #{P_SEARCH_TEXT_1}]]>
    </trim>
</if>
<if test="!P_SEARCH_TEXT_2.equals('%%'.toString())">
    <trim prefix="AND (" prefixOverrides="OR" suffix=")">
        <![CDATA[OR D.KOR_NM like #{P_SEARCH_TEXT_2}]]>
    </trim>
</if>
<if test="!P_SEARCH_TEXT_3.equals('%%'.toString())">
    <trim prefix="AND (" prefixOverrides="OR" suffix=")">
        <![CDATA[OR C.DEPT_NM like #{P_SEARCH_TEXT_3}]]>
    </trim>
</if>
cs

예시 2) index가 1000개 이상일 때마다 IN절을 새로 생성하고, 미만이면 suffixOverrides 속성을 사용해 IN절 구문 삭제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<if test="P_PJT_NO != null">
    AND ( A.PJT_NO IN
    <trim suffixOverrides = " OR A.PJT_NO IN ()">           
        <foreach collection="P_PJT_NO" index="index" item="item" open="(" close=")">
            <if test = "index != 0">
                <choose>
                    <when test = "index % 1000 == 999">) OR A.PJT_NO IN (</when>
                    <otherwise>,</otherwise>
                </choose>
            </if>
             #{item}
        </foreach>           
    </trim>
    )
</if>
cs

 

 

출처 : MyBatis Dynamic SQL Document

 https://mybatis.org/mybatis-3/dynamic-sql.html#trim-where-set

 

mybatis – MyBatis 3 | Dynamic SQL

Dynamic SQL One of the most powerful features of MyBatis has always been its Dynamic SQL capabilities. If you have any experience with JDBC or any similar framework, you understand how painful it is to conditionally concatenate strings of SQL together, mak

mybatis.org