내에 <query>를 이용하여, Query 서비스들을 통해 실행할 쿼리문들을 정의할 수 있다.
<queries> 내에는 여러 개의 <query>를 정의할 수 있다.
| Tag Name |
Description |
Child Tag |
| query |
쿼리문을 정의 한다.
* attribute설명
isDynamic : 동적 쿼리인지 아닌지 식별 (Default=true)
isCamelCase : 조회 결과 매핑시 조회 칼럼명에 대해 CamelCase 적용할 것인지 정의
(Default=true) |
statement(필수)
lobStatement(선택)
param(필수)
result(선택) |
| statement |
실행할 쿼리문을 정의한다. Joined 쿼리에서는 동일한 조회 칼럼명이 있을 경우,
Alias를 부여해야 한다. |
|
| param |
Query 서비스는 해당 쿼리문을 미리 컴파일하여 PreparedStatement 형태로 저장하여 처리하고 있다.
따라서 입력값 셋팅을 위해 PreparedStatement에 setXXX를 수행하려면, 입력 Parameter에 해당하는 SQL Type을
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','INOUT' 중 선택
name : CallableStatement경우 Stored Procedure 내에 정의된 변수 이름 정의 |
생략 시 VARCHAR로 인식됨 |
| result |
해당 쿼리가 조회를 위한 SELECT문일 경우에 사용할 수 있으며, 쿼리 수행 결과를 매핑할 클래스명을 정의한다.
<result>가 지정되지 않았을 경우 쿼리 수행 결과에 대해 하나의 Row에 대해 칼럼명, 해당값을 쌍으로 Map에 put하고
각 Row별 Map들을 ArrayList에 담은 형태로 결과값을 리턴하게 된다. isCamelCase가 true인 경우 Map에 저장되는
칼럼명에는 CamelCase가 적용됨에 유의하자. (즉, 칼럼명이 USER_NAME인 경우 Map의 키값은 userName이 된다.)
* attribute 설명
length : 한 페이지에 보여질 데이터의 건수
class : 수행 결과를 저장할 클래스명 |
result-mapping(선택) |
| result-mapping |
해당 쿼리가 조회를 위한 SELECT문일 경우에 사용할 수 있으며,
수행 결과를 저장할 클래스와 매핑되는 테이블이 존재하지 않을 경우, 조회된 칼럼별로 이에 매핑되는
해당 클래스의 attribute 명을 정의한다.
* attribute 설명
column : 조회된 칼럼명
attribute : 정의한 칼럼에 매핑되는 클래스의 attribute명
|
|
일반적인 사용
ECT문의 경우 특정 테이블과 매핑되는 클래스를 정의하지 않으면, 쿼리문 수행 결과는
각 Row에 대한 Map을 ArrayList에 담아 리턴된다.
각 Map으로부터 get("칼럼명")을 통해 해당 칼럼의 값을 얻을 수 있다.
<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-mapping>없이 해당 클래스명만
<result>에 정의해 두면 되므로 XML 정의가 보다 간단해진다. 또한 별도 쿼리문 정의없이 객체만으로도 단건
데이터 생성/수정/삭제/조회가 가능해진다.
<result class=""integration.anyframe.services.query.vo.CustomerVO"/>와 같이
table mapping시 사용한 클래스를 정의하면 쿼리문 수행 결과는 해당 클래스의 setter 호출을 통해 저장되고,
getter를 호출함으로써 결과값을 얻을 수 있게 된다.
<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>
<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>
<table-mapping>, <result-mapping>없이 <result>만을 이용할 경우
매핑 대상 클래스의 속성명이 조회 칼럼명과 동일하거나 CamelCase된 형태이어서, <table-mapping>나 <result-mapping>를
통해 별도 매핑을 수행하지 않아도 되는 경우에 사용할 수 있다. 즉, <result>의 클래스 속성 정보에 정의된
클래스의 속성과 조회된 칼럼명을 대상으로 CamelCase를 적용하여 다음과 같이 동작한다.
- 조회된 칼럼명을 CamelCase화하여 정의된 클래스의 속성중에서 찾아 매핑하고, 속성값 셋팅
(* 예를 들어 조회된 칼럼명이 USER_NAME이면, 매핑되는 속성명은 userName이 된다.)
<queryservice>
<!-- skipped -->
<queries>
<query id="getUser" isDynamic="false">
<statement>
SELECT USER_ID, USER_NAME, PASSWORD, SSN, SL_YN, BIRTH_DAY, AGE,
CELL_PHONE, ADDR, EMAIL, EMAIL_YN, IMAGE_FILE, REG_DATE
FROM USERS
WHERE USER_ID = ?
</statement>
<param type="VARCHAR" />
<result class="com.sds.emp.user.services.UserVO" />
</query>
</queries>
</queryservice>
* Query 서비스는 내부적으로 쿼리문 수행으로 얻어진 조회 결과를 매핑할 때 다음과 같은 순서로 매핑 기준을 찾는다.
- 정의된 <result-mapping> 정보가 있으면 이를 기반으로 매핑
- 정의된 <result> 클래스에 대한 <table-mapping> 정보가 있으면 이를 기반으로 매핑
- 정의된 <result> 클래스에 대한 정보가 있으면 이를 기반으로 매핑
- HashMap에 isCamelCase 속성값을 기반으로 매핑
<result-mapping>을 이용할 경우
<result-mapping>은 <table-mapping>에 정의되지 않은 클래스이면서, 조회된 칼럼명과 매핑 클래스의 속성명이
연관성이 없어 별도 매핑이 필요한 경우 사용한다.
주로 joined 쿼리문에서 사용할 수 있으며, <result-mapping>에 column과 attribute값을
일대일로 매핑한다. <result 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를 사용하면 정의된 조건에 따라 쿼리문을 수정하지 않고도 원하는 쿼리문을 실행할 수 있다.
#if($key.equals("true"))에서 'key'라는 키의 값이 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 유형의 데이터도 기본적으로 다른 데이터 유형들과 다르지 않으므로 매핑 xml도
일반적인 쿼리문 정의 방식과 같다.
<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에 설정해 놓고 그것을 호출해 오는 방식으로
일반 쿼리문보다 빠른 속도로 실행될 수 있다. 매핑 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>