ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [3-ch15 Spring ] MyBatis의 동적 태그 ( if, choose, trim)와 LIKE 사용 방법
    Back-End/Spring Legacy 2022. 8. 29. 14:30

     

    검색 기능과 SQL

     

    게시물의 검색 기능은 아래와 같이 분류가 가능하다.

    - 제목/내용/작성자와 같이 단일 항목 검색
    - 제목 or 내용 , 제목 or 작성자 ,,,, 같은 다중 항목 검색

     

    단일 항목 검색과, 복합적인 항목으로 검색하는 방식이 존재한다. 게시물 검색에 있어 가장 중요한 부분은 SQL인데, 오라클은 페이징 처리에 인라인뷰를 이용하기 때문에 실제로 검색 조건에 대한 처리는 인라인뷰 내부에서 이루어져야 한다.

     

     

    단일 항목에 경우 검색 조건에 따라서 칼럼이 달라지고 , LIKE 처리를 통해 키워드를 사용하게 된다. 

    만약 데이터를 '제목' 으로 하고 키워드를 '수정'으로 한다면 쿼리문은 다음과 같다. 

     

    select bno, title, content
    from ( select /*+ INDEX_DESC(tbl_board pk_board ) */ rownum rn, bno, title,content 
    from tbl_board
    where title like '%수정%' 
    and rownum <=10)
    where rn>=1;

     

     

    단일 항목은 인라인뷰 안쪽에서 필요한 데이터를 가져올 때 검색 조건이 적용되어야 하기 때문에 where문 뒤에 조건이 추가되고, rownum 조건이 뒤따르게 하면 된다.

     


     

     

     

    문제는, 2개 이상의 조건이 붙는 다중항목이다.

    만약 검색 조건이 제목 or 내용, 제목 or 작성자, 제목 or 내용 작성자 같은 처리가 필요하다면  연산자 and가 or보다 우선순위가 높기 때문에 다중 조건이 붙는다면 검색 조건을 ( ) 로 우선순위를 주어야 한다. 

     

    select bno, title, content
    from ( select /*+ INDEX_DESC(tbl_board pk_board ) */ rownum rn, bno, title,content 
    from tbl_board
    where (title like '%수정%' or content like '%컨트롤러%' )
    and rownum <=10)
    where rn>=1;

     

     

    content like '%컨트롤러%'가 추가되었으므로 위의 예제와 다르게 content에 컨트롤러가 들어간 게시글도 조회되는 것을 확인 가능하다. 

     

     

     

    MyBatis의 동적 태그들

     

     

    MyBatis에서는 기존의 iBatis에서 발전하면서 복잡했던 동적 SQL을 작성하는 태그들이 많이 정리되어 있다.  

     

     

    참고) 아래는 model1 방식에서 jsp를 이용해 검색 조건에 맞는 게시물 목록을 반환하는 쿼리 코드 

    //검색 조건에 맞는 게시물 목록을 반환합니다.
    public List<BoardDTO> selectList(Map<String, Object> map){
      List<BoardDTO> bbs = new Vector<BoardDTO>();
      //결과 (게시물 목록)를 담을 변수
      String query = "SELECT * FROM board";
    
      if (map.get("searchWord") != null) {
         query += " WHERE " + map.get("searchField") + " "
               + " LIKE '%" + map.get("searchWord") + "%' ";
      }
      //내림차순으로 게시글 num을 정리해라
      query += " ORDER BY num DESC ";
    
      try {
         stmt = con.createStatement(); //쿼리문 실행
         rs = stmt.executeQuery(query); //쿼리 실행
    
         while (rs.next()) { //결과를 순화하며...
            //한 행(게시물 하나)의 내용을 DTO에 저장
            BoardDTO dto = new BoardDTO();
    
            //dto에다가 rs 즉 BoardDTO에서 가져온 num의 값
            //이건 아까 더미데이터 추가했을 때 넘어간 값들을 가져온다.
            //가져온 값들을 dto에 저장하는 과정
            dto.setNum(rs.getString("num"));  //일련번호
            dto.setTitle(rs.getString("title")); //제목
            dto.setContent(rs.getString("content")); //내용
            dto.setPostdate(rs.getDate("postdate")); //작성일
            dto.setId(rs.getString("id")); //작성자 아이디
            dto.setVisitcount(rs.getString("visitcount"));//조회수
    
            bbs.add(dto); //결과 목록에 저장
            }
         }catch (Exception e) {
            System.out.println("게시물 조회 중 예외 발생");
            e.printStackTrace();
      }
      return bbs;
    }

     

     

    게시판 검색 조건에 있어 MyBatis의 동적 태그들 중 아래 몇 가지만 이용할 예정이다.

     

    - if
    - choose (when, otherwise)
    - trim (where, set)
    - foreach

     

     

    ● <if> 

     

    if는 test라는 속성과 함께 특정한 조건이 true가 되었을 때,  포함한 SQL을 사용하고자 할 때 작성한다. 예를 들어, 단일 항목으로 제목(title), 내용 (content), 작성자(writer)에 대해 검색하야 하는 상황이라고 가정한다. 

     

    - 검색조건이 'T'면 제목(title)이 키워드인 항목을 검색
    - 검색조건이 'C' 면 내용(content) / 검색조건이 'W'면 작성자(writer) 가 키워드인 항목 검색

     

    <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>

     

     

    ● <choose>

     

    if와 달리 choose는 여러 상황들 중 하나의 상황에서만 동작한다. Java 언어의 if~else나 JSTL의 <choose>와 유사하다. otherwise는 위의 조건이 모두 충족되지 않았을 경우 사용한다. 

     

    <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>

     

     

    ● <trim>, <where>, <set>

     

    trim, where, set은 단독으로 사용하지 않고 <if>, <choose>와 같은 태그들을 내포하여 SQL을 연결해주고, 앞 뒤에 필요한 구문들(AND, OR, WHERE) 을 추가하거나 생략하는 역할을 한다. 

     

    <where>은 태그 안쪽 SQL이 생성될 때는 구문이 붙고, 그렇지 않은 경우 생성되지 않는다. 예를들어 WHERE 태그 안에 IF 태그가 있을 때 그 조건이 참이면 WHERE 구문이 생성되고 FALSE면 생성되지 않는다는 의미이다. 

     

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

     

     

    select * from tbl_board
    	<where>
        	<if test="bno != null">
            	bno = #{bno}
            </if>
        	<trim prifix="and">
            rownum = 1
            </trim>
       </where>

     

    bno 값이 존재하는 경우 ->   select * from tbl_board where bno = 33 and rownum = 1
    bno 값이 존재하지 않는 경우 ->   select * from tbl board where rownum =1

     

     

     

     

     

     

     

     

    반응형

    댓글

Designed by Tistory.