Query Service

쿼리문이나 객체의 입력만으로 DB 데이터 조작을 가능하게 하는 서비스이다. Query 서비스는 JDBC(Java Database Connectivity)를 이용한 데이터 액세스 수행 부분을 추상화함으로써 간편한 데이터 액세스 방법을 제공하고, JDBC 사용시 발생할 수 있는 공통 에러를 줄여주게 된다. Query 서비스는 내부적으로 DataSource 서비스를 이용하고 있으므로, DataSource 서비스와 같이 배포되어야 한다.
Query 서비스에 대한 구현체는 1가지이며, 다음은 각 구현체별 사용법이다. 아래 상세 가이드를 참조하면 Query Service를 쉽게 이용할 수 있다.

DefaultQueryService

다음은 Query 서비스를 사용하기 위해 필요한 설정 정보들이다.
Property Name
Description
Required
Default Value
jdbcTemplate 참조할 jdbcTemplate service의 bean id
Y
N/A

Query Service는 jdbcTemplate를 참조하고 jdbcTemplate는 DataSource Service를 참조하므로써 Query Service가 jdbcTemplate을 이용하여 Connection 객체를 얻는다. 다음은 QueryService가 참조하는 jdbcTemplate을 위해 필요한 설정 정보들이다.
Property Name
Description
Required
Default Value
dataSource 참조할 dataSource service의 bean id
Y
N/A

Tag Name
Attrubute Name
Description
Required
Default Value
Child Tag
config:configuration filename properties
filename 테이블 매핑 정보와 사용할 쿼리문을 정의하고 있는 파일명을 지정하는 요소로 복수 지정 가능하다. filename 요소에 대한 지정은 절대 / 상대적인 파일 경로 지정 방법과 Classpath를 이용한 지정 방식의 2가지가 있다. Classpath를 이용하여 매핑 파일 정보를 지정하고자 할 경우 classpath:로 시작한다.
N
N/A
nullcheck 해당 DB Column의 값이 없는 경우, null value가 리턴되었을 때, 지정한 값으로 변환시켜준다.
N
N/A
sqlload dynamic SQL Mapping 파일에 대한 동적 Reload 설정여부를 정의한다.
N
frequency Reload 주기를 세팅한다.(miliseconds 단위) 1000미만 입력시 -> 1000으로 인식하며, 1000이상 입력시 -> 입력값으로 인식한다.
N
skiperror error 발생 시 skip 여부를 세팅한다.
N

Samples

  • Query Service Configuration
  • 다음은 Query Service에서 사용할 query의 속성을 정의한 applicationContext-query-general.xml의 일부이다.
    <bean name="queryService" class="anyframe.core.query.impl.QueryServiceImpl">
        <property name="jdbcTemplate">
           <ref bean="jdbcTemplate"/>
        </property>
        <config:configuration>
           <filename>classpath:mappings/mapping-general-query.xml</filename>
           <nullcheck type="VARCHAR" default-value=""/>
               <sqlload dynamic="false" frequency="5"/>
               <skiperror>true</skiperror>
        </config:configuration>
    </bean>
    
    <!-- The original JdbcTemplate definition -->
    <bean id="jdbcTemplate" class="anyframe.core.query.impl.util.PagingJdbcTemplate">
      <property name="dataSource" ref="common_datasource" />
    </bean>
  • TestCase
  • 다음은 Query Service를 사용하여 Database에 샘플 data를 INSERT, SELECT, UPDATE, DELETE하는 QueryServiceTestGeneral.java 코드의 일부이다.
    다음은 INSERT 예제이다.
    public void testInsertQuery() throws Exception{
        IQueryService queryService = (IQueryService) context.getBean("queryService");
        //create() : XML mapping파일에 정의되어 있는 SQL query를 이용하여 INSERT를 실행한다.
        int rs = queryService.create("create", new Object[] { "1234567890123", "AAAAA" , "seoul"});
        if ( rs == -1 ){
           throw new Exception("Insert query failed");
        }
    }
    다음은 SELECT 예제이다.
    public void testSelectQuery() throws Exception{
    	IQueryService queryService = (IQueryService) context.getBean("queryService");
    	//find() : XML mapping파일에 정의되어 있는 SQL query를 이용하여 SELECT를 실행한다.	//일반적인 경우(table과 class를 mapping하지 않은 경우)
    	ArrayList rsquery  = (ArrayList) queryService
    	                        .find("selectGeneral", new Object[] { "%12345%" });
    	Map hsRsquery = new HashMap();
    	for( int i = 0 ; i < rsquery.size() ; i ++ ){
    		hsRsquery = (Map) rsquery.get(i);
    		String name = (String) hsRsquery.get("name");
    	}
    	/*매핑 XML에 해당 클래스와 매핑되는 테이블이 존재하지 않을 경우,
    	* 쿼리 수행 결과에 대해 하나의 Row별로 칼럼명,
    	* 해당값을 쌍으로 org.apache.commons.collections.map.ListOrderedMap에 put하고 
    	* ListOrderedMap들을 ArrayList에 담은 형태로 결과값을 리턴하게 된다.
    	*/	
    	//Table - Class mapping을 사용한 경우
    	Collection rsqueryNotUsingResultMapping = queryService
    	               .find("selectNotUsingResultMapping", new Object[] { "%12345%" });
    	Iterator rsqueryItr = rsqueryNotUsingResultMapping.iterator();
    	while (rsqueryItr.hasNext()) {
    		CustomerVO customer = (CustomerVO) rsqueryItr.next();
    		String name =  customer.getNm();
    	}
    
    	//result-mapping을 사용 한 경우
    	Collection rsqueryUsingResultMapping = queryService
    	                .find("selectUsingResultMapping", new Object[] { "%12345%" });
    	Iterator rsqueryItr_01 = rsqueryUsingResultMapping.iterator();
    	while (rsqueryItr_01.hasNext()) {
    		CompositionCustomerVO compositionCustomer 
    		                                 = (CompositionCustomerVO) rsqueryItr_01.next();
    		String name =  compositionCustomer.getCompositionName();
    	}
    	
    	if( rsquery.size() != 1 ){
    		throw new Exception("Select query failed");
    	}
    	if( rsqueryNotUsingResultMapping.size() != 1 ){
    		throw new Exception("Select query failed");
    	}
    	if( rsqueryUsingResultMapping.size() != 1 ){
    		throw new Exception("Select query failed");
    	}
    }
    다음은 UPDATE 예제이다.
    public void testUpdateQuery() throws Exception {
    	IQueryService queryService = (IQueryService) context
    	.getBean("queryService");
    	//update() : XML mapping파일에 정의되어 있는 SQL query를 이용하여 UPDATE를 실행한다.
    	int rs = queryService.update("update"
    	                , new Object[] { "9999999999999", "AAAAA" , "busan" , "1234567890123"});
    	if ( rs == -1 ){
    		throw new Exception("Update query failed");
    	}
    }
    다음은 DELETE 예제이다.
    public void testDeleteQuery() throws Exception {
    	IQueryService queryService = (IQueryService) context
    	.getBean("queryService");
    	//remove() : XML mapping파일에 정의되어 있는 SQL query를 이용하여 DELETE를  실행한다.
    	int rs = queryService.remove("delete", new Object[] { "9999999999999" });
    	if ( rs == -1 ){
    		throw new Exception("Delete query failed");
    	}
    }
    앞서 소개된 샘플 테스트 코드를 포함하여 QueryService 소개 페이지에서 제공하는 모든 샘플 테스트 코드는 HSQL DB를 기반으로 실행된다. 단, ※ CallableStatement, LOB의 경우는 Oracle 9i, 10g를 기반으로 함.)

Resources

  • 다운로드
  • 샘플 테스트 코드를 포함하고 있는 anyframe-querytest-src.zip 파일을 다운받은 후, 테스트 환경 설정을 참조하여 위에서 제시한 예제 코드를 실행해 볼 수 있다.
    Name
    Download
    anyframe-querytest-src.zip
    Download