본문 바로가기

DATABASE/sql

[Mybatis]동적 SQL

반응형

SQL 문을 작성해서 데이터를 처리할 때 검색 조건이 변하면 sql문 역시 변하기 때문에 

MyBatis에서는 동적 태그 기능을 통해서 sql을 파라미터 조건에 맞도록 조정할 수 있다.

 

MyBatis에서 사용되는 동적 태그는 아래와 같다.

- if

- choose (when, otherwise)

- trim ( where, set)

- foreach

 

<if>

if는 test라는 속성과 함께 특정한 조건이 true가 되었을 때 포함된 sql을 사용하고자 할때 작성한다.

1
2
3
4
5
6
7
8
9
<if test="type == 'T'.toString()">
    (title like '%'||#{keyword}||'%')
</if>
<if test="type == 'C'.toString()">
    (content like '%'||#{keyword}||'%')
</if>
<if test="type == 'W'.toString()">
    (writer like '%'||#{keyword}||'%')
</if>
cs

**mysql에서는 %기호와 keyword를 합칠때 다음의 함수를 이용한다.

 => CONCAT('%',#{keyword},'%')

 

<choose>

if와 달리 choose는 여러 상황들 중 하나의 상황에서만 동작한다.(if ~else와 유사하다.)

otherwise는 위의 조건에 모두 충족하지 못했을 때 사용된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<choose>
    <when test="type == 'T'.toString()">
        (title like '%'||#{keyword}||'%')
    </when>
    <when test="type == 'C'.toString()">
        (content like '%'||#{keyword}||'%')
    </when>
    <when test="type == 'W'.toString()">
        (writer like '%'||#{keyword}||'%')
    </when>
    <otherwise>
        (title like '%'||#{keyword}||'%' OR content like '%'||#{keyword}||'%')
    </otherwise>
</choose>
cs

 

<trim>, <where>, <set>

위의 3가지는 <if>, <choose>와 같은 태그들을 내포하여 SQL들을 연결해 주고 앞 뒤에 필요한 구문들(AND, OR, WHERE 등)을 추가하거나 생략하는 역할을 한다.

 

<where>의 경우 태그 내부에 sql문이 조건에 따라 생성된다면 where구문이 생성되고 그렇지 않다면 생성되지 않는다.

또한 sql문이 and나 or로 시작한다면 그 and나 or를 지워 버린다.

1
2
3
4
5
6
7
select * from tbl_board
    <where>
        <if test="bno != null">
            bno = #{bno}
        </if>
    </where>
 
cs

 

bno가 존재하면

select * from tbl_board where bno = 11

 

존재하지 않으면

select * from tbl_board

 

 

<trim>은 하위에서 만들어지는 sql 문을 조사하여 앞 쪽에 추가적인 sql을 넣을 수 있다.

trim 속성

- prefix, suffix, prefixOverrides, suffixOverrides

1
2
3
4
5
6
7
8
9
10
select * from tbl_board
    <where>
        <if test = "bno != null">
            bno = #{bno}
        </if>
        <trim prefixOverrides = "and">
            rownum = 1
        </trim>
    </where>
 
cs

 

bno가 존재하면

select * from tbl_board where bno = 11 and rownum = 1

존재하지 않으면

select * from tbl_board where rownum = 1

 

<foreach>

foreach는 List, 배열, 맵 등을 이용해서 루프를 처리할 수 있다.

 

ex)

Map<String, String> map = new HashMap<>();

map.put("T", "TTTT");

map.put("C", "CCCC");

map.put("W", "CCCC");

 

collection에 대한 값은 getter가 존재하여야 MyBatis로 전달할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
select * from tbl_board
    <trim prefix= " where ( " suffix=")" prefixOverrides="OR">
        <foreach item="val" index="key" collection="map">
            <trim prefix ="OR">
                <if test="key == 'C'.toString()">
                    content = #{val}
                </if>
                <if test="key == 'T'.toString()">
                    title = #{val}
                </if>
                <if test="key == 'W'.toString()">
                    writer = #{val}
                </if>
            </trim>
        </foreach>
    </trim>
            
cs

 

select * from tbl_board

where ( content = ? OR title = ?)

 

select * from tbl_board where (content = 'CCCC' OR title = 'TTTT')

 

위와 같이 처리 되는 것을 알 수 있다.

반응형

'DATABASE > sql' 카테고리의 다른 글

[Database] 외래키  (0) 2021.03.23