DataBase/My SQL

[MyBatis] 동적쿼리문 <if, choose, when, otherwise, sql, include> (if~then/elseif~then 사용불가)

유혁스쿨 2020. 9. 7. 17:40
728x90
반응형

MyBatis에서의 동적 쿼리문 처리방법

 

JDBC방식의 Servlet이나 jdbcTemplate에서 사용되는 기본적인 동적(if,else) sql문 입니다

SELECT * FROM 
(SELECT rownum rnum, board_no, title, content, writer, reg_date, view_cnt 
FROM (SELECT * FROM mvc_board 
WHERE IF #{condition} == '' THEN 
ELSEIF #{condition} == title THEN
title like '%'||#{keyword}||'%'
ELSEIF #{condition} == content THEN
content like '%'||#{keyword}||'%'
ORDER BY board_no DESC))
WHERE  rnum BETWEEN #{startRow} AND #{endRow}

하지만 마이바티스에서는 일반 if else문을 사용할수 없으며 xml에서 <if>태그를 지원해줍니다.

<if>

SELECT * FROM 
(SELECT rowNum rNum board_no, title, content, writer, reg_date, view_cnt FROM
(SELECT * FROM mvc_board    
<if test="condition == ''"></if> <!--생략가능합니다 -->
<if test="condition == 'title'">
where board_title like '%'||#{keyword}||'%' 
</if>
<if test="condition == 'content'">
where board_cont like '%'||#{keyword}||'%'
</if>
<if test="condition == 'titleContent'">
where board_title like '%'||#{keyword}||'%' 
OR board_cont like '%'||#{keyword}||'%'
</if>
order by board_no desc)) 
where rNum &lt;= #{startRow} and rNum &lt;= #{endRow}

<where>

SELECT * FROM 
(SELECT rowNum rNum board_no, title, content, writer, reg_date, view_cnt FROM
(SELECT * FROM mvc_board    
<where>
<if test="condition == ''"></if> <!--생략가능합니다 -->
<if test="condition == 'title'">
board_title like '%'||#{keyword}||'%' 
</if>
<if test="condition == 'content'">
board_cont like '%'||#{keyword}||'%'
</if>
<if test="condition == 'titleContent'">
title like '%'||#{keyword}||'%' 
OR content like '%'||#{keyword}||'%'
</if>
</where>     
order by board_no desc)) 
where rNum &lt;= #{startRow} and rNum &lt;= #{endRow}

 

 

 

 

위와 같이 마이바티스 xml파일의 SQL문에서 동적쿼리인 <if>태그를 사용할때 test 속성을 사용하는데

이 test 속성을 통해서 if문을 분기하기 위한 비교 구문을 작성합니다.

 

        <select id="condition" name="condition">
                <option value="title">제목</option>
                <option value="content">내용</option>
                <option value="titleContent">제목+내용</option>
        </select>
        <input type="text" name="keyword" id="keywordInput" placeholder="검색어">
        <input type="button" value="검색"  id="searchBtn">

<select>에서 name속성은 condition이며 condition 이라는 네임에 선택된 option value의 파라미터값이 실려서 네임:값 쌍으로 컨트롤러로 넘어갑니다.

 

우선 앞서 말했듯 <if> 태그는 test 라는 속성을 통해 분기를 합니다.

test속성에는 비교구문이 들어갑니다.

비교구문이 true라면 현재의 test속성이 선언된 <if> 태그 내부의 구문을 적용하여 쿼리문이 작동됩니다.


<if test="condition == ''"></if> <!--생략가능합니다 -->
<if test="condition == 'title'">
board_title like '%'||#{keyword}||'%' 
</if>
<if test="condition == 'content'">
board_cont like '%'||#{keyword}||'%'
</if>
<if test="condition == 'titleContent'">
title like '%'||#{keyword}||'%' 
OR content like '%'||#{keyword}||'%'
</if>

(Mysql에서는 Concat함수를 사용해야한다!!!!! 아래 코드) 

<if test="condition == ''"></if> <!--생략가능합니다 -->
<if test = "searchOption == 'title'">
board_title LIKE CONCAT('%', #{keyword}, '%')
</if>
<if test = "searchOption == 'content'">
board_cont LIKE CONCAT('%', #{keyword}, '%')
</if>
<if test = "searchOption == 'titleContent'">
board_title LIKE CONCAT('%', #{keyword}, '%') OR board_cont LIKE CONCAT('%', #{keyword}, '%')
</if>

 

예를들어 위와같이 

condition 네임의 파라미터값이 title과 같은지 비교 결과가  true라면 현재의 test 속성이 적용된 <if> 태그 내부의 구문을 

condition 네임의 파라미터값이 content과 같은지 비교 결과가  true라면 현재의 test 속성이 적용된 <if> 태그 내부의 구문을 

condition 네임의 파라미터값이 titleContent와 같은지 비교 결과가 true라면 현재의 test 속성이 적용된 <if> 태그 내부의 구문을 적용하여 쿼리문이 작동하게 되는 것 입니다.

 

(추가적으로 이때 파라미터는 condition과 keyword 두가지이기 때문에 VO객체로 한번에 넘어오겠죠?)


<sql>,<include>

만약 공통적으로 사용해야할 때가 있습니다

공통적으로 사용해야 한다면 <sql>태그로 id속성값을 부여하여 공통적으로 사용될 부분만 미리 선언해두고

<sql id="search"> </sql>

<include refid="search"/>  

<include>태그에 refid속성으로 공통쿼리id를 선언만해주면다면 언제든지  참조하여 사용할 수 있게됩니다.

 

<sql id="search">
    <where>
        <if test="condition == ''"></if> <!--생략가능합니다 -->
        <if test="condition == 'title'">
            board_title like '%'||#{keyword}||'%' 
        </if>
        <if test="condition == 'content'">
            board_cont like '%'||#{keyword}||'%'
        </if>
        <if test="condition == 'titleContent'">
            title like '%'||#{keyword}||'%' 
            R content like '%'||#{keyword}||'%'
        </if>
    </where>     
<sql>

 

<select id="getArticleList" resultMap="BoardMap">
    SELECT * FROM 
    (SELECT rownum rnum, board_no, title, content, writer, reg_date, view_cnt FROM 
    (SELECT * FROM mvc_board 
        
    <include refid="search"/>
    
    ORDER BY board_no DESC))         
    WHERE  rnum BETWEEN #{startRow} AND #{endRow}
</select>
	
<select id="countArticles" resultType="int">
		SELECT COUNT(*) 
		FROM mvc_board 
        
		<include refid="search"/>        
</select>

 

<sql>,<include>태그로의 참조방법은 동적쿼리문을 떠나서 모든 쿼리문을 다 묶어두고 참조하여 활용할수 있게됩니다

 

728x90
반응형