Query Service - Mapping XML Files

Query Service 초기화시, Query Service는 속성 정의 파일에 정의되어 있는 mapping xml file을 로드한다. 그리고 사용자 요청시 mapping 정보를 기반으로 올바른 query를 찾아 실행한다.
Mapping XML file은 <queryservice>와 </queryservice>내에 크게 table-mapping tag와 queries tag로 구성된다. table-mapping tag와 queries tag는 필수 요소이므로 빠뜨리지 않도록 주의해야 한다.

table-mapping tag 정의 방법

table-mapping tag는 테이블과 클래스간의 매핑 정보들을 정의한다.
Tag Name
Description
Child Tag
table 테이블과 클래스간의 매핑 정보를 정의한다.
* attribute 설명
name: 해당 테이블명
class : 매핑 클래스명
field-mapping(필수)
primary-key(필수)
field-mapping 테이블의 칼럼과 이에 매핑되는 클래스의 attribute를 정의한다.
dbms-column(필수)
class-attribute(필수)
primary-key 해당 테이블의 Primary Key를 정의한다.
dbms-column(필수)
class-attribute(필수)
dbms-column 해당 테이블의 칼럼명을 정의하며, 테이블의 칼럼 순서와 일치해야 한다.
class-attributes dbms-column에서 정의한 칼럼과 매핑되는 해당 클래스의 attribute명을 정의한다.

다음은 위에서 나열한 설정 정보들을 이용한 table-mapping tag 설정 예제이다. 테이블 TBL_CUSTOMER와 클래스 CustomerVO간의 매핑 정보를 담고 있다.
<queryservice>
    <table-mapping>
       <table name="TBL_CUSTOMER"
       class="integration.anyframe.services.query.vo.CustomerVO">
          <field-mapping>
             <dbms-column>ssno</dbms-column>
             <class-attribute>ssno</class-attribute>
          </field-mapping>
          <field-mapping>
             <dbms-column>name</dbms-column>
             <class-attribute>nm</class-attribute>
          </field-mapping>
          <field-mapping>
             <dbms-column>address</dbms-column>
             <class-attribute>addr</class-attribute>
          </field-mapping>
          <primary-key>
             <dbms-column>ssno</dbms-column>
          </primary-key>
       </table>
    </table-mapping>
    <!-- skipped -->
</queryservice>

queries tag 정의 방법

queries tag는 쿼리문들을 정의한다.

Tag Name
Description
Child Tag
query 쿼리문을 정의 한다.
* attribute설명
isDynamic : 동적 쿼리인지 아닌지 식별
statement(필수)
lobStatement(선택)
param(필수)
result(선택)
statement 사용하고자 하는 쿼리문을 정의한다. Joined 쿼리에서 동일한 조회 칼럼명이 있을 경우, Alias 명을 부여해야 한다.
param Query 서비스는 SQL 쿼리를 미리 컴파일하여 PreparedStatement 형태로 저장하여 쿼리를 처리하고 있다. 따라서 setXXX를 수행하기 위해 입력 Parameter의 SQL Type을 jdk API java.sql.Types에 정의된 값을 참조하여 param tag의 attribute인 type에 정의한다. param tag는 입력 Parameter의 개수와 순서에 맞게 추가한다.
입력 Parameter의 데이터를 가져오기 위해서는 다음과 같은 기준에 따라 데이터 타입을 정의해야만 한다
   ---------------------------------------
   Java Type                DBMS Type
   ---------------------------------------
   String                   CHAR
   String                   VARCHAR
   String                   LONGVARCHAR
   java.math.BigDecimal	    NUMERIC
   java.math.BigDecimal	    DECIMAL
   boolean                  BIT
   byte                     TINYINT
   short                    SMALLINT
   int                      INTEGER
   long                     BIGINT
   float                    REAL
   double                   FLOAT
   double                   DOUBLE
   byte[]                   BINARY
   byte[]                   VARBINARY
   byte[]                   LONGVARBINARY
   java.sql.Date            DATE
   java.sql.Time            TIME
   java.sql.Timestamp       TIMESTAMP
   ---------------------------------------
* attribute 설정
type : parameter의 DBMS type
binding : CallableStatement경우 'IN' 또는 'OUT'를 선택
name : CallableStatement경우 Stored Procedure의 변수 이름 설정
생략 시 VARCHAR로 인식됨
result 해당 쿼리가 SELECT문일 경우에 사용하며, 쿼리 수행 결과를 저장할 클래스명을 정의한다. result tag가 지정되지 않았을 경우 쿼리 수행 결과에 대해 하나의 Row별로 칼럼명, 해당값을 쌍으로 Map에 put하고 Map들을 ArrayList에 담은 형태로 결과값을 리턴하게 된다.
* attribute 설명
length : 한 페이지에 보여질 데이터 건수
class : 수행 결과를 저장할 클래스명
result-mapping(선택)
result-mapping 해당 쿼리가 SELECT문일 경우에 사용하며, 수행 결과를 저장할 클래스와 매핑되는 테이블이 존재하지 않을 경우, 조회된 칼럼별로 이에 매핑되는 해당 클래스의 attribute 명을 정의한다.
* attribute 설명
column : 조회된 칼럼명
attribute : 정의한 칼럼에 매핑되는 클래스의 attribute명

다음은 위에서 나열한 설정 정보들을 이용한 다양한 queries tag 설정 예제이다.

  • 일반적인 사용
  • SELECT query문의 경우 table과 mapping되는 VO Class를 정의하지 않은 경우에 query수행 결과를 Column Name, 해당값을 Row별로 Map에 put하고 각 Row들에 대한 Map를 ArrayList형태로 리턴한다. get("Column name")를 통해서 해당 column의 값을 얻을 수 있다.
    <queryservice>
        <!-- skipped -->
        <queries>
           <query id="selectGeneral" isDynamic="false">
              <statement>
                 SELECT * FROM TBL_CUSTOMER WHERE SSNO like ?
              </statement>
              <param type="VARCHAR" />
           </query>
        </queries>
    </queryservice>
  • result-mapping이 없고 table-mapping을 이용할 경우
  • <result class=""integration.anyframe.services.query.vo.CustomerVO"/>와 같이 table mapping시 사용한 class를 정의하면 query문의 수행값이 해당 class의 settter를 통해 저장되고, getter를 이용해 결과값을 얻을 수 있다.
    <queryservice>
        <!-- skipped -->
        <queries>
           <query id="select" isDynamic="false">
              <statement>
                 SELECT * FROM TBL_CUSTOMER WHERE SSNO like ?
              </statement>
              <param type="VARCHAR" />
              <result class="integration.anyframe.services.query.vo.CustomerVO"/>
           </query>
        </queries>
    </queryservice>
  • result-mapping을 이용할 경우
  • result-mapping은 <table-mapping>에서 table과 class mapping를 정의하지 않은 경우 사용한다. 주로 joined query문에서 사용하고 result-mapping에서 column과 attribute값을 일대일로 mapping하여 정의한다. result class에서 정의된 Class의 setter를 통해 저장되고, getter를 이용해 결과값을 얻을 수 있다.
    <queryservice>
        <!-- skipped -->
        <queries>
           <query id="selectUsingResultMapping" isDynamic="false">
              <statement>SELECT * FROM TBL_CUSTOMER WHERE SSNO like ?</statement>
              <param type="VARCHAR"/>
              <result class="integration.anyframe.services.query.vo.CompositionCustomerVO">
                 <result-mapping column="NAME" attribute="nm"/>
                 <result-mapping column="ADDRESS" attribute="addr"/>
              </result>
           </query>
        </queries>
    </queryservice>
  • dynamic query인 경우
  • dynamic query를 사용하면 조건에 따라 쿼리문을 수정하지 않고도 원하는 query를 실행할 수 있다. #if($key.equals("true"))에서 'key'라는 key값을 가진 파라미터의 value가 true이면 OR NAME like '%test%' 의 쿼리문이 실행된다.
    <queryservice>
        <!-- skipped -->
        <queries>
           <query id="dynamicsample" isDynamic="true">
              <statement>select NAME, ADDRESS from TBL_CUSTOMER 
                 where NAME like :name
                      #if($key.equals("true"))
                        OR NAME like '%test%'
                      #end>
              </statement>
              <param name="name" type="VARCHAR"/>
           </query> 
        </queries>
    </queryservice>
  • LOB(Large Object)를 이용할 경우
  • LOB 파일은 기본적으로 다른 data와 다르지 않으므로 mapping xml도 일반적인 Query 정의 방식과 같다.
    <queryservice>
        <!-- skipped -->
        <queries>
           <query id="lobsample" isDynamci="false">
              <statement>insert into binary values(?,?,?)</statement>
              <param type="INTEGER"/>
              <param type="BLOB"/>
              <param type="CLOB"/>
           </query>
        </queries>
    </queryservice>
  • CallableStatement일 경우
  • CallableStatement는 프로시져나 함수를 미리 DB에 설정해 놓고 그것을 호출해 오는 방식으로 일반 쿼리보다 빠른 속도로 실행된다. mapping xml에서는 쿼리문을 직접 입력하지 않고 프로시져나 함수를 call하기만 하면 된다.
    <queryservice>
        <!-- skipped -->
        <queries>
           <query id="callablesample">
              <statement>
                 {? = call java_refcursor.job_listing (?)}
              </statement>
              <param type="CURSOR" binding="OUT" name="out_Val" />
              <param type="VARCHAR" binding="IN" name="in_Val" />
           </query>
        </queries>
    </queryservice>