RIA Query Service

Web Framewore의 UI를 Ajax UI Component나 X-internet기반의 MI Platform을 활용할 경우 개발의 편의성과 응답속도 향상을 위해 최적화된 RIA Query 서비스를 제공한다. 단순 조회화면의 경우 DAO 없이 구현이 가능하므로 개발시간이 감소하여 짧은 납기내에 많은 사용자 UI를 구현해야 할 경우 특히 유용하다. 내부적으로 기존 Query 서비스와 Extended Query서비스를 이용하고 있으므로, Query 서비스와 Extended Query서비스가 같이 배포되어야 한다.
RIA Query 서비스에 대한 구현체는 2가지이며, 다음은 각 구현체별 사용법이다.

Common configuration

다음은 MIPSQLService, NitobiSQLService를 사용하기 위해 공통으로 필요한 SQLService를 설정하기 위해 필요한 정보들이며 MIPSQLService, NitobiSQLService는 SQLService를 참조하여 구현된 Bean이다.
Property Name
Description
Required
Default Value
jdbcTemplate 참조할 jdbcTemplate service의 bean id
Y
N/A
sqlRepository 참조할 sqlLoader service의 bean id
Y
N/A
lobHandler 참조할 lobHandler service의 bean id
Y
N/A

RIA Service도 Extended Query서비스와 동일하게 sqlLoader가 별도의 bean으로 분리되었으며 jdbcTemplate과 lobHandler를 설정하는 것은 동일하다.

다음은 sqlLoader 설정시 필요한 정보들이다.
Tag Name
Attrubute Name
Description
Required
Default Value
Child Tag
config:configuration filename nullcheck
filename 테이블 매핑 정보와 사용할 쿼리문을 정의하고 있는 파일명을 지정하는 요소로 복수 지정 가능하다. filename 요소에 대한 지정은 절대 / 상대적인 파일 경로 지정 방법과 Classpath를 이용한 지정 방식의 2가지가 있다. Classpath를 이용하여 매핑 파일 정보를 지정하고자 할 경우 classpath:로 시작한다.
N
N/A
nullcheck 해당 DB Column의 값이 없는 경우, null value가 리턴되었을 때, 지정한 값으로 변환시켜준다.
N
N/A
property name="skiperror" error 발생 시 skip 여부를 세팅한다.
N

MIPSQLService

Query Service Configuration

다음은 Query Service에서 사용할 query의 속성을 정의한 applicationContext-mipsqlquery-general.xml의 일부이다.

applicationContext-mipsqlquery-general.xml
<bean name="sqlService" class="anyframe.core.query.impl.SQLServiceImpl">
	<property name="jdbcTemplate">
		<ref bean="pagingNamedParamJdbcTemplate"/>
	</property>
	<property name="lobHandler">
		<ref bean="lobHandler"/>
	</property>			
	<property name="sqlRepository">
		<ref bean="sqlLoader"/>
	</property>							
</bean>	

<bean id="MIPSqlService" parent="txConfig">
	<property name="target">
		<bean class="anyframe.core.query.impl.mip.MIPSQLServiceImpl">
			<property name="sqlService">
				<ref bean="sqlService"/>
			</property>		
			<property name="sqlRepository">
				<ref bean="sqlLoader"/>
			</property>							
		</bean>	
	</property>
	<property name="proxyInterfaces"
		value="anyframe.core.query.MIPSQLService" />
</bean>		

사용 sample

RIA QueryService는 DAO구현 없이 Web Framework에서 직접 호출이 가능하며 개발자는 Query XML파일에 실행sql을 기술하는것으로 작업이 완료된다.

  • Action클래스
  • Web Framework으로 struts를 이용하여 Action 클래스를 작성시 DefaultMIActionSupport및 DefaultMIDispatchActionSupport 를 이용하여 손쉽게 개발이 가능하다.
    DefaultMIDispatchActionSupport 클래스를 상속 받아 아래 소스코드와 같이 Action 클래스에서 해당Query를 실행한 결과를 받아올 수 있다. 다음은 DefaultMIDispatchActionSupport 이용하여 실 구현한 MiCategoryDispatchAction.java이다.
    MiCategoryDispatchAction.java
    public class MiCategoryDispatchAction extends DefaultMIDispatchActionSupport {
      
      public void selectCategoryList(ActionMapping mapping, PlatformRequest request,
          VariableList inVl, DatasetList inDl, VariableList outVl,
          DatasetList outDl) throws Exception {
        
        MIPSQLService sqlService = (MIPSQLService)getService("MISQLService");
        Dataset dsAccess = sqlService.search("getMiCategoryList", inVl);
        outDl.addDataset("ds_access",dsAccess);
      }
    
      public void updateCategory(ActionMapping mapping, PlatformRequest request,
          VariableList inVl, DatasetList inDl, VariableList outVl,
          DatasetList outDl) throws Exception {
    
        MIPSQLService sqlService = (MIPSQLService)getService("MISQLService");
        Map sqlMap = new HashMap();
        sqlMap.put(MIPSQLService.QUERY_INSERT, "insertCATEGORY_MI");
        sqlMap.put(MIPSQLService.QUERY_UPDATE, "updateCATEGORY_MI");
        sqlMap.put(MIPSQLService.QUERY_DELETE, "deleteCATEGORY_MI");
        sqlService.update(sqlMap, inDl.getDataset("ds_input"), new MiActionCommand(){
    
          public void postDelete(Dataset arg0, int arg1) {
          }
    
          public void postInsert(Dataset arg0, int arg1) {
          }
    
          public void postUpdate(Dataset arg0, int arg1) {
          }
    
          public void preDelete(Dataset ds, int index) {
          }
    
          public void preInsert(Dataset ds, int index) {
            IIdGenerationService idGenerationService 
              = (IIdGenerationService)getService("idGenerationServiceCategory");
            try {
              String id = idGenerationService.getNextStringId();
              Variant variant = new Variant();
              variant.setObject(id);    
              ds.setColumn(index,"categoryNo", variant);
            } catch (BaseException e) {
              e.printStackTrace();
              throw new RuntimeException(e);
            }
          }
          public void preUpdate(Dataset arg0, int arg1) {
          }});
      }
      
    }
    상단의 소스에 기술된 selectCategory, updateCategory메소드내 구현부분에 대한 상세한 설명은 다음과 같다.

    유형
    MIPSQLService
    사용method
    API
    비고
    조회시 select Dataset search(String queryId, VariableList variablelist)
    Dataset search(String queryId, Dataset dataset)
    Variable, Dataset 두 형태 모두 Argument로 가능
    수정시 update void update(HashMap queryMap, Dataset dataset) 전달하는 인자인 dataset에는 insert,update,delete하는 모든 record를 포함하고 있으며 insert,update,delete에 해당하는 query id를 각각 queryMap에 지정한다


    MIPSQLService의 update 메소드의 MIActionCommand는 CUD 작업을 실행하기 전/후처리가 필요한 경우 사용하며 필요한 비즈니스 로직을 추가할 수 있다.

    MiActionCommand에는 6개의 method(preInsert, preUpdate, preDelete, postInsert, postUpdate, postDelete)가 정의되어 있으며 해당 method에 수행해야 할 비즈니스 로직을 구현하면 된다.
    상단소스의 updateCategory에서는 신규 Category 정보를 추가하기 전에 Category No를 IdGenerationService으로 생성하는 로직을 preInsert에서 정의하고 있다.

  • Query XML
  • 다음은 mapping-mipsql-query.xml 예제이다.

    MIPSQLQuery 서비스를 이용하는 경우 Extended Query서비스를 사용할 때와 달리 parameter를 ‘:vo.변수명’ 형태가 아닌 ‘:변수명’으로 정의해 주어야 한다. 하단의 예제의 경우 MiCategoryDispatchAction의 selectCategoryList, updateCategory함수에 정의된 query id를 확인할 수 있다.
    <queryservice>
    <queries>
      <query id="findByPkCATEGORY_MI" isDynamic="true">
        <statement>
          SELECT
          CATEGORY_NO, CATEGORY_NAME, CATEGORY_DESC, USE_YN, REG_ID,        
          REG_DATE, MODIFY_ID, MODIFY_DATE, FILE_REF_ID       
          FROM CATEGORY
          WHERE CATEGORY_NO=:categoryNo       
        </statement>
        <result class="anyframe.templates.emp.mi.category.service.MiCategoryVO"></result>
      </query>  
        <query id="insertCATEGORY_MI" isDynamic="true">
        <statement>
          INSERT INTO CATEGORY
          ( CATEGORY_NO, CATEGORY_NAME, CATEGORY_DESC, USE_YN, REG_ID,        
          REG_DATE, MODIFY_ID, MODIFY_DATE, FILE_REF_ID )
          VALUES ( :categoryNo, :categoryName, :categoryDesc, :useYn, :regId,         
          SYSDATE, :modifyId, SYSDATE, :fileRefId  )
        </statement>
      </query>
      <query id="updateCATEGORY_MI" isDynamic="true">
        <statement>
          UPDATE CATEGORY
          SET CATEGORY_NAME=:categoryName, CATEGORY_DESC=:categoryDesc, USE_YN=:useYn, 
          REG_ID=:regId, REG_DATE=SYSDATE, MODIFY_ID=:modifyId, MODIFY_DATE=SYSDATE, 
          FILE_REF_ID=:fileRefId        
          WHERE CATEGORY_NO = :categoryNo       
        </statement>
      </query>
      <query id="deleteCATEGORY_MI" isDynamic="true">
        <statement>
          DELETE FROM CATEGORY
          WHERE CATEGORY_NO=:categoryNo       
        </statement>
      </query>
    </queries>
    </queryservice>
    

NitobiSQLService

Query Service Configuration

다음은 Query Service에서 사용할 query의 속성을 정의한 applicationContext-nitobisqlquery-general.xml의 일부이다.

applicationContext-nitobisqlquery-general.xml
<bean name="sqlService" class="anyframe.core.query.impl.SQLServiceImpl">
	<property name="jdbcTemplate">
		<ref bean="pagingNamedParamJdbcTemplate"/>
	</property>
	<property name="lobHandler">
		<ref bean="lobHandler"/>
	</property>			
	<property name="sqlRepository">
		<ref bean="sqlLoader"/>
	</property>							
</bean>	

<bean id="NitobiSQLService" parent="txConfig">
	<property name="target">
		<bean class="anyframe.core.query.impl.nitobi.NitobiSQLServiceImpl">
			<property name="sqlService">
				<ref bean="sqlService"/>
			</property>		
			<property name="sqlRepository">
				<ref bean="sqlLoader"/>
			</property>							
		</bean>	
	</property>
	<property name="proxyInterfaces"
		value="anyframe.core.query.NitobiSQLService" />
</bean>	

사용 sample

RIA QueryService는 DAO구현 없이 Web Framework에서 직접 호출이 가능하며 개발자는 Query XML파일에 실행sql을 기술하는것으로 작업이 완료된다.

  • Action클래스
  • Web Framework으로 struts를 이용하여 Action 클래스를 작성시 조회시는 CommonListAction을, 수정시는 AbstractNitobiUpdateAction 을 상속받아 손쉽게 개발이 가능하다.
    다음은 CommonListAction을 이용하여 실 구현한 AJAXGetCategoryAction.java이다.
    AJAXGetCategoryAction.java
    public class AJAXGetCategoryAction extends CommonListAction{
      public ActionForward selectCategoryList(ActionMapping mapping, ValueObject vo,
          HttpServletRequest request, HttpServletResponse response)
          throws Exception {  
        /*
         * LIVE SCROLLING 기능을 위한 PARAMETER를 SETTING
         */
        CommonSearchVO searchVO = (CommonSearchVO)vo;
        String startRecordIndexString = request.getParameter("StartRecordIndex");
        String pageSizeString = request.getParameter("PageSize");
        startRecordIndexString = (startRecordIndexString == null) 
                                        ? "1":startRecordIndexString;
        pageSizeString = (pageSizeString == null) ? "1":pageSizeString;
        int startRecordIndex = new Integer(startRecordIndexString).intValue();
        int pageSize = new Integer(pageSizeString).intValue();
        
        if(request.getParameter("SortColumn") != null 
              && !request.getParameter("SortColumn").equals("") ){
          searchVO.setSortColumn(request.getParameter("SortColumn"));
          searchVO.setSortDirection(request.getParameter("SortDirection"));
        }
        
        Map paramMap = new HashMap();
        populateParameter(request, paramMap);
        paramMap.put("vo", searchVO);
        NitobiSQLService queryService = (NitobiSQLService) getService("NitobiSQLService");
        GetHandler getHandler = queryService.search(getQueryId(mapping, vo, request, response),
                                          paramMap,startRecordIndex,pageSize);
        getHandler.writeToClient(response);
        return null;
      }
    }
    CommonListAction을 상속하여 구현시 반드시 지켜야 할 규칙이 존재하며 다음과 같다.

    UI component에서 호출할 때 <ajax:grid gethandler="../../../AjaxGetCategoryList.do?method=selectCategoryList">
    struts-config.xml에서 action mapping시 <action path="/AjaxGetCategoryList" type="com.sds.web.ajax.action.AjaxGetCategoryList"/>
    query xml에서 실행query id <query id="AjaxGetCategoryList">


    다음은 AbstractNitobiUpdateAction 이용하여 실 구현한 AjaxSaveCategoryAction.java이다.
    AjaxSaveCategoryAction.java
    public class AjaxSaveCategoryAction extends AbstractNitobiUpdateAction {
    
      protected String getDeleteQueryID() {
        return "deleteCATEGORY_Nitobi";
      }
    
      protected String getInsertQueryID() {
        return "insertCATEGORY_Nitobi";
      }
    
      protected String getUpdateQueryID() {
        return "updateCATEGORY_Nitobi";
      }
    
      protected NitobiActionCommand getActionCommand() {
        IIdGenerationService idGenerationService 
        = (IIdGenerationService)getWebApplicationContext().getBean("idGenerationServiceAjaxCategory");
        return new CategoryActionCommand(idGenerationService );
      }
    
      class CategoryActionCommand extends DefaultNitobiActionCommand{
        
        final private IIdGenerationService idGenerationService;
        
        CategoryActionCommand(IIdGenerationService idGenerationService){
          this.idGenerationService = idGenerationService;
        }
      
        public void preInsert(Record record) {
          String categoryNo = null;
          try {
            categoryNo = idGenerationService.getNextStringId();
            record.setField("categoryNo", categoryNo);
          } catch (Exception e) {
            throw new RuntimeException(e);
          }     
        }
      }
    
    }
    AJAXGetCategoryListAction에서 NitobiSQLService를 이용한 CUD작업에서 전/후처리가 필요한 경우 MIActionCommand와 유사한 DefaultNitobiActionCommand을 이용하여 필요한 비즈니스 로직을 추가할 수 있다.

    DefaultNitobiActionCommand에는 6개의 method(preInsert, preUpdate, preDelete, postInsert, postUpdate, postDelete)가 정의되어 있으며 해당 method에 수행해야 할 비즈니스 로직을 구현하면 된다.
    상단소스의 CategoryActionCommand에서는 신규 Category 정보를 추가하기 전에 Category No를 IdGenerationService로 생성하는 로직을 preInsert에서 정의하고 있다.



  • Query XML
  • 다음은 mapping-nitobisql-query.xml 예제이다.

    NitobiSQLQuery 서비스를 이용하는 경우 Extended Query서비스를 사용할 때와 동일하게 parameter를 ‘:vo.변수명’ 형태로 정의해 주어야 한다. MIPSQLQuery서비스와는 상이하므로 주의한다. 하단의 예제의 경우 AJAXGetCategoryListAction와 AjaxSaveCategoryAction클래스에 정의된 query id를 확인할 수 있다.
    <queryservice>
    <queries>
      <query id="AjaxGetCategoryList" isDynamic="true">
        <statement>
          SELECT
          CATEGORY_NO, CATEGORY_NAME, CATEGORY_DESC, USE_YN, REG_ID,        
          REG_DATE, MODIFY_ID, MODIFY_DATE, FILE_REF_ID
          FROM CATEGORY
          WHERE CATEGORY_NO=:vo.categoryNo        
        </statement>
        <result class="anyframe.templates.emp.mi.category.service.MiCategoryVO"></result>
      </query>  
        <query id="insertCATEGORY_Nitobi" isDynamic="true">
        <statement>
          INSERT INTO CATEGORY 
          ( CATEGORY_NO, CATEGORY_NAME, CATEGORY_DESC, USE_YN, REG_ID,        
          REG_DATE, MODIFY_ID, MODIFY_DATE, FILE_REF_ID )
          VALUES ( :vo.categoryNo, :vo.categoryName, :vo.categoryDesc, :vo.useYn, 
          :vo.regId, SYSDATE, :vo.modifyId, SYSDATE, :vo.fileRefId  )
        </statement>
      </query>
      <query id="updateCATEGORY_Nitobi" isDynamic="true">
        <statement>
          UPDATE CATEGORY
          SET CATEGORY_NAME=:vo.categoryName, CATEGORY_DESC=:vo.categoryDesc, 
          USE_YN=:vo.useYn, REG_ID=:vo.regId, REG_DATE=SYSDATE, MODIFY_ID=:vo.modifyId,
          MODIFY_DATE=SYSDATE, FILE_REF_ID=:vo.fileRefId        
          WHERE CATEGORY_NO = :vo.categoryNo        
        </statement>
      </query>
      <query id="deleteCATEGORY_Nitobi" isDynamic="true">
        <statement>
          DELETE FROM CATEGORY
          WHERE CATEGORY_NO=:vo.categoryNo        
        </statement>
      </query>
    </queries>
    </queryservice>