[iBatis] queryForMap() 사용법

프로그래밍/Framework 2009. 4. 21. 18:57 Posted by galad
참조: http://openframework.or.kr/Wiki.jsp?page=QueryForMapExample

<resultMap id="AccountResult" class="Account">
  <result property="id" column="ACC_ID"/>
  <result property="firstName" column="ACC_FIRST_NAME"/>
  <result property="lastName" column="ACC_LAST_NAME"/>
  <result property="emailAddress" column="ACC_EMAIL"/>
</resultMap>


<select id=
"selectAllAccounts" resultMap="AccountResult">
  select * from ACCOUNT
</select>

위와 같은 iBatis sql문에 대해 다음과 같이 쿼리.

queryForMap("selectAllAccounts", null, "id");

파라미터는 null이고, 쿼리 결과를 Map으로 받는데 키는 id에 대응하는 ACC_ID 칼럼값이 된다.
테이블에서는 모든 값(칼럼)을 가져와서 Accout 클래스형으로 값을 저장.
즉, key=ACC_ID칼럼값, value=Account클래스의 형태의 Map이 된다.

queryForMap("selectAllAccounts", null, "id""emailAddress");

역시 파라미터는 null이고 결과를 Map으로 받는데, 키는 id에 대응하는 ACC_ID 칼럼값이며,
값은 emailAddress에 대응하는 ACC_EMAIL칼럼값만 가져온다.
즉, key=ACC_ID칼럼값, value=ACC_EMAIL칼럼값의 형태의 Map이 된다.

두번째 사용법.

<statement id="getContentType" resultClass="org.apache.commons.collections.SequencedHashMap">
    SELECT * FROM OMPDBA.CONTENT_TYPE WHERE STATUS = 'U'
</statement>

위와 같이 resultMap이 없는 경우.

queryForMap(sqlId, paramMap, keyColumn, valueColumn);

파라미터명으로 써있는데로, 실제 칼럼명 자체를 파라미터로 넘겨준다.

중요.
    <statement id="SELECT_SERVICE_TYPE" resultClass="java.util.HashMap">
        SELECT
            a.SERVICE_TYPE, b.SERVICE_TYPE_NAME
        FROM
            CONTENT_SERVICE_SYSTEM a, SERVICE_TYPE b
        WHERE
            a.SERVICE_TYPE = b.SERVICE_TYPE
            AND a.CONTENT_TYPE = #PARAM0#
            AND b.STATUS = 'U'
        ORDER BY
            b.DISPLAY_ORDER ASC
    </statement>


위의 두번째 사용법에서 resultClass에 주목.
queryForMap은 결과를 map으로 돌려주는 것이므로, 위의 쿼리 결과는 SequencedHashMap이 Map안에 들어간 형태로 나와버린다?
이건 아닌 듯. resultClass 속성을 삭제하면 결과가 String으로 나와버림.
원하는 key-value형태로 나오지 않음.
java.util.HashMap(Map아님. interface라 안되는듯)으로 하면, ORDER BY 해도 순서가 제멋대로.
org.apache.commons.collections.map.ListOrderedMap로 해도 순서가 제멋대로.
즉, 키-값으로 넣을 수 있는 것이 반드시 resultClass 또는 resultMap 속성에 와야 하지만, 그렇다고 순서를 보장하진 않음.(Map답네..)

[iBatis] iterate 사용법

프로그래밍/Framework 2009. 4. 13. 20:13 Posted by galad
    <statement id="CHECK_SUB_CONTENT_TYPE_FOR_DELETE" resultClass="java.lang.String">
        SELECT
            COUNT(*) TOTAL_COUNT
        FROM
            SUB_CONTENT_TYPE
        <iterate prepend="WHERE" property="deleteContentTypeList" open="("  conjunction="," close=")">
            CONTENT_TYPE IN #deleteContentTypeList[]#
        </iterate>
    </statement>

    <statement id="CHECK_SUB_CONTENT_TYPE_FOR_DELETE" resultClass="java.lang.String">
        SELECT
            COUNT(*) TOTAL_COUNT
        FROM
            SUB_CONTENT_TYPE
        <iterate prepend="WHERE CONTENT_TYPE IN " property="deleteContentTypeList" open="("  conjunction="," close=")">
            #deleteContentTypeList[]#
        </iterate>
    </statement>

    <statement id="CHECK_SUB_CONTENT_TYPE_FOR_DELETE" parameterClass="java.util.List" resultClass="java.lang.String">
        SELECT
            COUNT(*) TOTAL_COUNT
        FROM
            SUB_CONTENT_TYPE
        <dynamic prepend="WHERE">
            <iterate property="deleteContentTypeList" open="("  conjunction="," close=")">
                CONTENT_TYPE IN #deleteContentTypeList[]#
            </iterate>
        </dynamic>
    </statement>

버근지 뭔지 몰라도 위의 방식은 하나도 안된다. property속성을 쓰면 안되는건지...
근데 되는 사람들도 있는 것 같고..

    <statement id="CHECK_SUB_CONTENT_TYPE_FOR_DELETE" resultClass="java.lang.String">
        SELECT
            COUNT(*) TOTAL_COUNT
        FROM
            SUB_CONTENT_TYPE
        <dynamic prepend="WHERE">
            <iterate open="CONTENT_TYPE IN ("  close=")" conjunction="," >
                #[]#
            </iterate>
        </dynamic>
    </statement>

이것처럼 아예 property 속성을 없애고, list의 이름을 없이 하면 잘됨.

참고:http://lostsin.tistory.com/tag/iBATIS

sql의 xml설정은 다음과 같이 하고

     <delete id="deletes" >
          DELETE FROM users
          <dynamic prepend="WHERE id IN">
              <iterate open="(" conjunction="," close=")">
                  #[]#
              </iterate>
          </dynamic>
      </delete>


DAO는 다음과 같이 한다
    public int delete(Integer[] ids) {
        return getSqlMapClientTemplate().delete("users.deletes", ids);
    }

해당 쿼리는 <iterate> 구문에 의하여 WHERE id IN (1,2,3,4,5) 방식으로
값이 매핑되게 된다.


보너스1.
List<>를 사용하는 방법도 xml 쿼리 부분은 동일하다.

List<String> list = new ArrayList<String>(3);

list.add("1");

list.add("2");

list.add("3");

List objs = sqlMapClient.queryForList("select-test",list);




보너스2.
parameterClass="map" 을 사용할 땐

     WHERE

session_id IN

<iterate property="sessionIds" open="(" close=")" conjunction=",">

#key[]#

</iterate>

hash의 key 값으로 사용된 string을 지정해주면 된다 (?)

추가.
            HashMap map = new HashMap();
            map.put("deleteContentTypeList", deleteContentTypeList);
            map.put("updateId", updateId);
            map.put("updateTime", updateTime);
           
            this.update("contenttype.DELETE_CONTENT_TYPE", map);

    <statement id="DELETE_CONTENT_TYPE">
        UPDATE
            CONTENT_TYPE
        SET
              STATUS = 'D'
            , UPDATE_ID = #updateId#
            , UPDATE_TIME = #updateTime#
        <dynamic prepend="WHERE">
            <iterate property="deleteContentTypeList" open="CONTENT_TYPE IN (" close=")" conjunction=",">
                #deleteContentTypeList[]#
            </iterate>
        </dynamic>
    </statement>

이건 또 된다. map에 넣어서 넘겨주면 멀쩡히 잘 되는군...

# 추가
list 를 패러미터로 전달 시 iterate 태그에서 property 를 설정하면(map으로 넘겼을 떄 말고),
전달된 list 에서 해당 property 를 찾으려고 시도하는 것 같다.
<iterate> 태그에서 property 속성을 제거하면 정상적으로 작동한다.

<select id="selectSomething" parameterClass="list">
    // select something and use iterate
    <iterate> // iterate 태그 내 property 속성을 제거하라
        #someList[]#
    </iterate>
</select>

<statement id="SELECT_CONTENT_TYPE" resultMap="contenttype-resultMap">
        SELECT
            *
        FROM (
            SELECT
                ROWNUM ROWCNT,
                CONTENT_TYPE, CONTENT_TYPE_NAME, SUBSET_LIST_KEY, STATUS,
                DESCRIPTION_PAGE_NAME, INPUT_PAGE_NAME, DETAIL_VIEW_PAGE_NAME,
                CREATE_ID, CREATE_TIME, UPDATE_ID, UPDATE_TIME
            FROM
                CONTENT_TYPE
        )
        <dynamic prepend="WHERE">
            <isNotEmpty property="pageNavi.startRow">
                ROWCNT BETWEEN #pageNavi.startRow# AND #pageNavi.endRow#
            </isNotEmpty>
        </dynamic>
        <dynamic prepend="ORDER BY">
            <isNotEmpty property="orderColumn">
                $orderColumn$ $orderType$
            </isNotEmpty>
        </dynamic>
    </statement>

$orderColumn$ 인 것에 주목.
문자열 치환일 경우엔 $가 붙는다.
#은 preparedStatment에서 바인딩 하는 경우에 사용한다.(?에 값 넣는 경우처럼)

'프로그래밍 > Framework' 카테고리의 다른 글

[iBatis] iterate 사용법  (1) 2009.04.13
[Struts2] <s:iterator> <s:if> 사용법  (0) 2009.04.13
[iBatis] 동적쿼리문 생성  (0) 2009.04.13
[Struts2] <s:select> 사용법  (0) 2009.04.10
[Struts2] 태그에서 변수 사용법  (0) 2009.04.08

[iBatis] 동적쿼리문 생성

프로그래밍/Framework 2009. 4. 13. 16:08 Posted by galad
출처: http://narrowway.tistory.com/entry/iBatis%EB%8F%99%EC%A0%81-%EC%BF%BC%EB%A6%AC%EB%AC%B8-%EC%83%9D%EC%84%B1

<statement id="dynamicGetAccountList" resultMap="account-result">

  select * from account

  <dynamic prepend="WHERE">

    <isNotNull prepend="AND" property="firstName">

      (acc_first_name = #firstName#

    <isNotNull prepend="OR" property="lastName">

       acc_last_name = #lastName#

    </isNotNull>

    )

    </isNotNull>

    <isNotNull prepend="AND" property="emailAddress">

      acc_email like #emailAddress#

    </isNotNull>

    <isGreaterThan prepend="AND" property="id" campareValue="0">

      acc_id = #id#

    </isGreaterThan>

  </dynamic>

  order by acc_last_name

</statement>

 

상황에 의존적인 위 동적 statement로 부터 각각 다른 16가지의 SQL문이 생성될 수 있다. if-else구조와 문자열 연결을 코딩하는 경우 수백라인이 필요할 수도 있다.

동적 statement를 사용하는 것은 몇몇 조건적인 태그를 추가하는 것처럼 간단하게 작성할 수 있다.

 

이러한 조건들에 대해 간단히 정리하면 아래와 같다.

 

바이너리 조건 요소-바이너리 조건 요소는 정적값 또는 다른 프로퍼티값을 위한 프로퍼티값과 비교한다. 만약 결과가 true라면 몸체부분의 SQL쿼리가 포함된다.

 

바이너리 조건 속성

prepend

Statement에 붙을 오버라이딩 가능한 SQL부분(옵션)

property

비교되는 property(필수)

compareProperty

비교되는 다른 property (필수 또는 compareValue)

compareValue

비교되는 값(필수 또는 compareProperty)

 

<isEqual>

프로퍼티가 값 또는 다른 프로퍼티가 같은지 체크

<isNotEqual>

프로퍼티가 값 또는 다른 프로퍼티가 같지 않은지 체크

<isGreaterThan>

프로퍼티가 값 또는 다른 프로퍼티 보다 큰지 체크

<isGreaterEqual>

프로퍼티가 값 또는 다른 프로퍼티 보다 크거나 같은지 체크

<isLessThan>

프로퍼티가 값 또는 다른 프로퍼티 보다 작은지 체크

<isLessEqual>

프로퍼티가 값 또는 다른 프로퍼티 보다 작거나 같은지 체크

 

사용법 예제)

<isLessEqual prepend="AND" property="age" compareValue="18">

  ADOLESCENT = 'TRUE'

</isLessEqual>

 

단일 조건 요소-단일 조건 요소는 특수한 조건을 위해 프로퍼티의 상태를 체크한다.

prepend

statement에 붙을 오버라이딩 가능한 SQL부분(옵션)

property

체크하기 위한 프로퍼티(필수)

 

<isPropertyAvailable>

프로퍼티가 유효한지 체크

(이를 테면 파라미터의 프로퍼티이다.)

<isNotPropertyAvailable>

프로퍼티가 유효하지 않은지 체크

(이를 테면 파라미터의 프로퍼티가 아니다.)

<isNull>

프로퍼티가 null인지 체크

<isNotNull>

프로퍼티가 null이 아닌지 체크

<isEmpty>

Collection, 문자열 또는 String.valueOf() 프로퍼티가 null이거나 empty(“” or size() < 1)인지 체크

<isNotEmpty>

Collection, 문자열 또는 String.valueOf() 프로퍼티가 null 이아니거나 empty(“” or size() < 1)가 아닌지 체크

 

사용법 예제)

<isNotEmpty prepend="AND" property="firstName">

  FIRST_NAME = #firstName#

</isNotEmpty>


다른 요소들

Parameter Present : 파라미터 객체가 존재하는지 체크

Parameter Present Attributes : prepend - the statement에 붙을 오버라이딩 가능한 SQL부분

<isParameterPresent>

파라미터 객체가 존재(not null)하는지 체크

<isNotParameterPresent>

파라미터 객체가 존재하지(null) 않는지 체크

 

사용법 예제)

<isNotParameterPresent prepend="AND">

EMPLOYEE_TYPE = 'DEFAULT'

</isNotParameterPresent>


Iterate : 이 태그는 Collection을 반복하거나 리스트내 각각을 위해 몸체 부분을 반복한다.

Iterate Attributes :

  prepend - the statement에 붙을 오버라이딩 가능한 SQL부분 (옵션)

  property - 반복되기 위한 java.util.List타입의 프로퍼티 (필수)

  open - 반복의 전체를 열기 위한 문자열, 괄호를 위해 유용하다. (옵션)

  close - 반복의 전체를 닫기 위한 문자열, 괄호를 위해 유용하다. (옵션)

  conjunction - 각각의 반복 사이에 적용되기 위한 문자열, AND 그리고 OR을 위해 유용하다. (옵션)

<iterate>

java.util.List 타입의 프로퍼티 반복


사용법 예제)

<iterate prepend="AND" property="userNameList" open="(" close=")" conjunction="OR">

username = #userNameList[]#

</iterate>


주의:iterator요소를 사용할 때 리스트 프로퍼티의 끝에 중괄호[]를 포함하는 것은 중요하다. 중괄호는 문자열처럼 리스트를 간단하게 출력함으로부터 파서를 유지하기 위해 리스트처럼 객체를 구별한다.


출처: http://www.mail-archive.com/user-java@ibatis.apache.org/msg06617.html

forgot to register implementation in dao.xml