2009년 9월 9일 수요일

iBATIS 매핑


드디어 iBatis의 매핑 구문을 한 번 알아보도록 하자...

iBatis의 매핑 구문에는 select, insert, update, delete, statement, procedure, sql, include가 있는데...

그 중에 select 구문을 알아보도록 하자..

사실 저거 하나만 알면 나머지 구문은 자연스럽게 알 수가 있다..

간단하게 게시판을 조회하는 쿼리로 알아보도록 하자..

 

 <select id="getBoardListByName1"
         parameterClass="java.util.HashMap"
         resultClass="java.util.HashMap">
  <![CDATA[
   select t.*
     from  (select b.*, (select count(*)
                           from board_comment c
                          where b.id = c.board) as 'comment'
              from board_master b
             where b.board = #board:VARCHAR#
          order by b.group desc, b.order) t
    limit #startpage:INTEGER#, #count:INTEGER#
  ]]>
 </select>

 

실제 사용하는 코드는 다음과 같다...

Map parameter = new HashMap();
parameter.put("board", "freeboard");
parameter.put("startpage", new Integer(0));
parameter.put("count", new Integer(10));
  
List list = client.queryForList("getBoardListByName1", parameter);

 

일단 <select>에는 id, parameterMap, parameterClass, resultMap, resultClass 등의 속성이 존재한다...

위의 예제는 그 중에 parameterClass와 resultClass를 사용하는 방법을 보여주고 있다...

즉... select문을 수행하는 getBoardListByName이란 명령이 있고..

매개변수로는 HashMap을 받고 결과값을 HashMap으로 돌려준다는 얘기이다..

queryForList 메소드를 사용하면 결과 HashMap이 List에 저장된 형태로 리턴될 것이고..

queryForMap 메소드를 사용하면 결과 HashMap이 HashMap에 key에 따라 저장된 형태로 리턴될 것이다..

 

그럼 전달받은 매개변수는 어떻게 사용하면 되는가...

인라인 매개변수 매핑과 외부 매개변수 매핑 방식이 있는데 위에서 볼 수 있듯이 #을 사용하는 것이 인라인 매핑이라고 한다...

: 뒤에는 전달받은 매개변수의 데이터 타입을 명시해주는 것인데 성능향상에 도움이 된다고 한다...

java.sql.Types에 있는 데이터 타입을 사용하면 된다...

또한 인라인 매핑을 위해 $를 사용할 수도 있는데 SQL 주입 공격에 취약하므로 사용시 주의한다...

 

그렇다면 리턴값은 어떻게 설정해 주는가 보자..

리턴값은 자동 결과 매핑 방식과 명시적인 결과 매핑 방법이 있는데 위의 방법은 자동 결과 매핑 방식이다...

한마디로 아무것도 안 해줘도 알아서 매핑해준다는 것이다..

물론 자동으로 하다 보니 성능이 조금 떨어지고 유지보수가 어렵다는 단점이 존재하기도 한다..

 

그렇다면 외부 매개변수 매핑과 명시적인 결과 매핑은 어떻게 할까..

아래 2개의 예제를 보면 간단하게 알 수 있다...


<sqlMap>

 <parameterMap id="BoardListByNameParameter" class="java.util.HashMap">
  <parameter property="board" jdbcType="VARCHAR"/>
  <parameter property="startpage" jdbcType="INTEGER"/>
  <parameter property="count" jdbcType="INTEGER"/>
 </parameterMap>
 
 <resultMap id="BoardListByNameResult" class="java.util.HashMap">
  <result property="id" column="id"/>
  <result property="board" column="board"/>
  <result property="title" column="title"/>
  <result property="writer" column="writer"/>
  <result property="content" column="content"/>
  <result property="open" column="open"/>
  <result property="group" column="group"/>
  <result property="order" column="order"/>
  <result property="depth" column="depth"/>
  <result property="saveday" column="saveday"/>
  <result property="saveid" column="saveid"/>
  <result property="modifyday" column="modifyday"/>
  <result property="modifyid" column="modifyid"/>
  <result property="comment" column="comment"/>
 </resultMap>

 <select id="getBoardListByName2"
         parameterMap="BoardListByNameParameter"
         resultClass="java.util.HashMap">
  <![CDATA[
   select t.*
     from  (select b.*, (select count(*)
                           from board_comment c
                          where b.id = c.board) as 'comment'
              from board_master b
             where b.board = ?
          order by b.group desc, b.order) t
    limit ?, ?
  ]]>
 </select>
 
 <select id="getBoardListByName3"
         parameterMap="BoardListByNameParameter"
         resultMap="BoardListByNameResult">
  <![CDATA[
   select t.*
     from  (select b.*, (select count(*)
                           from board_comment c
                          where b.id = c.board) as 'comment'
              from board_master b
             where b.board = ?
          order by b.group desc, b.order) t
    limit ?, ?
  ]]>
 </select>

 

parameterMap과 resultMap을 사용하는 것을 볼 수 있다..

둘 다 class에는 어떤 타입의 자료형을 사용할 것인지 지정하는 것이고..

id 다른 태그에서 사용하던 것과 같은 의미이다...

그리구 둘 다 property 속성(parameterProperty, resultProperty)을 갖는데..

parameterProperty같은 경우는 전달받은 변수의 프로퍼티명을 지정해주면 되고...

resultProperty에는 결과로 전달할 변수의 프로퍼티명과 연결할 컬럼명을 지정해주면 된다...

물론 명시적으로 jdbcType이나 javaType을 지정해주는 것도 좋은 방법이다..

그리고 sql문에는 PreparedStatement에서 사용하는 것과 비슷하게 매개변수 지정을 ?로 바꿔준다..

?에 들어가는 순서는 차례대로 들어가게 되므로 잘 맞춰서 parameterMap을 작성한다..

getBoardListByName2는 parameterMap만 사용하고 있고..

getBoardListByName3는 둘 다 사용하는 모습을 볼 수 있다...

 

iBatis 책에서는 명시적인 방법을 추천하고 있다...

성능상에도 이점이 있고 무엇보다 유지보수가 편하다는 점을 들고 있다..

그리고 계속 자바빈즈를 사용하고 있는데 난 아무래도 자바빈즈보단 HashMap이 편하다...

다음에는 동적 쿼리에 대해 알아보도록 하자...

사실 이 책을 산 이유 중의 하나가 동적쿼리 때문이었다는... -_-;;

댓글 없음:

댓글 쓰기